docs(redesign): complete Phase 1 source audit
This commit is contained in:
@@ -38,3 +38,5 @@ AI should support this flow naturally and contextually. It must never invent fac
|
||||
## Status
|
||||
|
||||
These documents define the intended target state. They should be updated as the remaining functional work is completed. The full redesign implementation should begin only after a stable pre-redesign baseline has been created and protected by tests.
|
||||
|
||||
2026-09-09: [Phase 1 source audit](audit/README.md) completed on `codex/ui-redesign-audit`: current routes, protected functionality, component/test/API inventories, identity/storage boundaries and proposed migration gates. No redesign implementation or B07 started. Required release checks and F04 production verification remain separate from this audit's completion.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# API integration and identity boundaries
|
||||
|
||||
## Transport
|
||||
|
||||
[api.ts](../../../job-tracker-ui/src/api.ts) is the shared Axios transport. Production uses `/api`; local development defaults to port 5202 unless `NEXT_PUBLIC_API_BASE_URL` overrides it. The value is embedded in the static build. All discovered direct frontend `api`/`axios` calls are in [API_CALL_SITES](API_CALL_SITES.md); UI wrappers such as `cvBuilder`, `aiWorkspace` and `applicationWorkspace` are included. SDK OAuth/navigation and server-to-server provider calls are separate from that census.
|
||||
|
||||
Credentialed requests use the HttpOnly auth cookie and XSRF handling. B02 adds immutable session provenance, cancellation and late-response rejection. Downloads use authorized blob requests where required; B05 CSV bytes must not be decoded/re-encoded through `Blob.text()`. Error handling uses shared extraction plus screen-specific recovery. A new fetch/cache/form abstraction must preserve all of these behaviors.
|
||||
|
||||
## Domain contract map
|
||||
|
||||
Paths are relative to `/api`. See the linked census for each method, interpolated ID and exact source line. DTOs are in [frontend types](../../../job-tracker-ui/src/types.ts), domain wrappers, and [API controllers](../../../JobTrackerApi/Controllers).
|
||||
|
||||
| Frontend owner | API groups | Identity / mutation contract |
|
||||
|---|---|---|
|
||||
| Login/account/security cards | `/auth/config`, `/auth/me`, login/register/reset/verification, `/auth/profile`, avatar, email-change, 2FA, sessions, language preferences | Public challenge/setup entry versus authenticated self-account actions; client never chooses authoritative owner |
|
||||
| Table/Kanban/edit/add | `/jobapplications`, `/board`, choices, duplicate-check, status, restore; `/companies` and relationship | Owner-scoped job/company lookup and associations; status changes and soft deletion distinct from creation intent |
|
||||
| Capture/discovery | `/jobimport/preview`, `/job-discovery/search`, saved-searches/results, Gmail suggested jobs | Review/preview and create separate; B01 connection enforcement; saved searches belong to account |
|
||||
| Personal analytics/reminders | Dashboard/statistics call sites, reminders/rules, notification-settings | Current-account reporting and dates; global/admin reporting separate |
|
||||
| Full/overlay job workspace | `/jobapplications/:id/workspace`, timeline, analysis, match, CV, tailoring, cover-letter, drafts, submitted-packages, checklist, interview-prep, follow-up | Job owner boundary plus nested artifact IDs; workspace aggregate reads do not authorize child writes |
|
||||
| Profile/evidence | `/career/profile`, versions/restore, `/career/evidence`, `/profile-cv/*` | Principal-owned singleton; extraction proposal review; history/projection distinct from CV overrides |
|
||||
| CV library/editor | `/cv/*` through `cvBuilderApi`, themes, outline, variant save/copy/history/publish/preview/export | Private owner + resource ID; job association validates same owner; B03 admission shared with other PDF callers |
|
||||
| Public CV | Public-CV slug endpoints | Anonymous access only through explicitly published variant; not arbitrary private ID download |
|
||||
| Contextual AI | `/ai/usage`, `/jobapplications/:id/ai/modules`, generate/history; profile and CV AI endpoints | Server entitlement, context ownership/consent and quotas; UI accept step does not replace backend authorization |
|
||||
| Documents | `/attachments/*`, submitted-package attachments, PDF export | Authorized upload/download/delete and scoped references; preserve content disposition and blob handling |
|
||||
| Correspondence/mail | `/correspondence/*`, `/gmail/*`, `/microsoft-graph/*`, `/imap/*`, `/email/providers`, message, drafts, send | OAuth mailbox distinct from login; owner/job association, draft revision, send attempt/delivery state |
|
||||
| Calendar | `/calendar/status`, `/calendar/jobs/:id/events`, `events.ics` | Owned job dates + provider permission; date-only and UTC timestamp semantics remain distinct |
|
||||
| Operations/notifications | `/operations`, cancel/retry, `/notifications`, read/dismiss | Owner-scoped asynchronous work; rerender does not mean enqueue again |
|
||||
| Export/lifecycle/billing | `/export/jobs`, `/export/account`, `/backup/encrypted`, `/account-lifecycle/*`, `/billing/status`, checkout/portal | Owner data; recent-auth/destructive/provider constraints; B05 at CSV boundary |
|
||||
| Admin | `/users`, `/admin/audit`, `/admin/system` and maintenance/email/AI subroutes | Server Admin role; sensitive system views kept separate from personal workspace |
|
||||
|
||||
No backend contract changes are proposed for Phase 1. API endpoint names and old route query values are compatibility surface even if new screen labels differ.
|
||||
|
||||
## Authentication and authorization
|
||||
|
||||
[Program.cs](../../../JobTrackerApi/Program.cs#L299) configures the smart authentication selector and local/provider validation. Local bearer or cookie JWT validation includes issuer/audience/signature/lifetime and a live local-session validation step. Production account-aware policies resolve authenticated identity before limiting. Relevant middleware order is forwarded headers/security/routing/CORS and CSRF handling, then [authentication → authorization → rate limiter → B02 SessionContextMiddleware → controllers](../../../JobTrackerApi/Program.cs#L654). Do not move owner limiting ahead of authentication during shell/API cleanup.
|
||||
|
||||
[CurrentUserService](../../../JobTrackerApi/Services/CurrentUserService.cs) derives local owner identity from the principal. Its background-owner scope cannot replace an HTTP request identity. [JobTrackerContext](../../../JobTrackerApi/Data/JobTrackerContext.cs#L132) uses live owner evaluation and fail-closed query filters. These are additional guards; not a license to remove explicit ownership checks from services or to introduce unscoped `IgnoreQueryFilters()` calls.
|
||||
|
||||
The [CV service](../../../JobTrackerApi/Services/CvVariantService.cs#L74) looks up `id + owner` and validates job associations with `jobId + owner`. Its explicit public lookup bypasses ordinary filters only for the published-slug path. Career Profile PUT derives the owner from current authentication and updates that singleton, explaining why B02 session provenance is separate from ID-based authorization. The old retained A form replay under B was not simply an IDOR. B02 now rejects retained/missing/forged session provenance server-side; the client also unmounts/aborts private state.
|
||||
|
||||
Admin controllers enforce Admin roles; Pro operations have server entitlement checks. The permissive default in `AccountPlanContext` is for isolated previews, while routed App supplies server-backed values. It is not proof that an ordinary user can obtain Pro server access. The frontend's auth/config and role-based navigation are presentation logic; a stale or crafted frontend must remain constrained by the API.
|
||||
|
||||
This is an integration map with targeted service verification, not a fresh claim that every authorization path in the application has been penetration-tested. Keep the permanent B01–B06 tests and original independent audit evidence.
|
||||
|
||||
## State and storage map
|
||||
|
||||
| State | Current scope | Preservation condition |
|
||||
|---|---|---|
|
||||
| Auth credential | HttpOnly cookie; CSRF companion cookie | Do not move tokens into browser storage or let client headers select owner |
|
||||
| `authUserKey`, auth persistence preferences | Browser identity marker/preferences | Not an authoritative server identity; B02 handles account-generation change |
|
||||
| `authSessionContext` storage signal | Cross-tab change notification | Immutable per page context; stale work aborts/reauthenticates, it does not adopt B's identity |
|
||||
| Form/editor state and workspace tab cache | React/component memory | Dispose on B02 invalidation; preserve unsaved-navigation guard within one identity |
|
||||
| Dashboard visibility | `dashboardPrefs:<owner>` localStorage | Owner-scoped, five booleans; not cross-device persistence |
|
||||
| Saved job views, headline fallback, onboarding dismissal | Owner-keyed localStorage | Never rehydrate A's private view/draft data into B's page |
|
||||
| Theme/language/sidebar collapse/table page size and columns | Device/browser preferences (language also server-hydrated) | These are presentation preferences, not private document caches |
|
||||
| Pro notice dismissal | Feature-keyed sessionStorage | Presentation-only; no CV/account content, entitlement still server-derived |
|
||||
| Mail drafts / application drafts / CV history | Server persistence with domain-specific APIs | Preserve each existing contract; do not replace with a generic browser draft mechanism |
|
||||
|
||||
Sources: [auth.ts](../../../job-tracker-ui/src/auth.ts), [sessionBoundary.ts](../../../job-tracker-ui/src/sessionBoundary.ts), [App.tsx](../../../job-tracker-ui/src/App.tsx), `SavedViewsMenu`, `DashboardView`, `ProfilePage`, `ProFeatureNotice`. Any future cache must be account-scoped and must not replay mutations after the page's identity generation changes. Record revision conflicts, identity isolation and duplicate-creation idempotency remain **three distinct contracts**.
|
||||
@@ -0,0 +1,272 @@
|
||||
# API call-site inventory
|
||||
|
||||
Generated with the installed TypeScript AST from the committed baseline. Each row is an actual `api`/`axios` call expression, not a claim of runtime test coverage. Paths are relative to the shared `/api` base; interpolations are preserved. Domain wrappers are included. Companion technical audit maps contracts and authorization.
|
||||
|
||||
| Source | Method | URL expression |
|
||||
|---|---|---|
|
||||
| [src/App.tsx:189](../../../job-tracker-ui/src/App.tsx#L189) | GET | "/auth/config" |
|
||||
| [src/App.tsx:206](../../../job-tracker-ui/src/App.tsx#L206) | GET | "/auth/me" |
|
||||
| [src/App.tsx:229](../../../job-tracker-ui/src/App.tsx#L229) | GET | "/jobapplications/reminders" |
|
||||
| [src/App.tsx:237](../../../job-tracker-ui/src/App.tsx#L237) | GET | "/notifications/unread-count" |
|
||||
| [src/App.tsx:250](../../../job-tracker-ui/src/App.tsx#L250) | GET | "/auth/me" |
|
||||
| [src/App.tsx:374](../../../job-tracker-ui/src/App.tsx#L374) | POST | "/auth/logout" |
|
||||
| [src/aiWorkspace.ts:29](../../../job-tracker-ui/src/aiWorkspace.ts#L29) | GET | "/ai/usage" |
|
||||
| [src/aiWorkspace.ts:30](../../../job-tracker-ui/src/aiWorkspace.ts#L30) | GET | `/jobapplications/${jobId}/ai/modules` |
|
||||
| [src/aiWorkspace.ts:32](../../../job-tracker-ui/src/aiWorkspace.ts#L32) | POST | `/jobapplications/${jobId}/ai/generate` |
|
||||
| [src/aiWorkspace.ts:34](../../../job-tracker-ui/src/aiWorkspace.ts#L34) | GET | `/jobapplications/${jobId}/ai/history` |
|
||||
| [src/aiWorkspace.ts:35](../../../job-tracker-ui/src/aiWorkspace.ts#L35) | DELETE | `/jobapplications/${jobId}/ai/history/${id}` |
|
||||
| [src/applicationWorkspace.ts:114](../../../job-tracker-ui/src/applicationWorkspace.ts#L114) | GET | `/jobapplications/${jobId}/workspace` |
|
||||
| [src/applicationWorkspace.ts:188](../../../job-tracker-ui/src/applicationWorkspace.ts#L188) | GET | `/jobapplications/${jobId}/timeline` |
|
||||
| [src/applicationWorkspace.ts:194](../../../job-tracker-ui/src/applicationWorkspace.ts#L194) | GET | `/jobapplications/${jobId}/analysis` |
|
||||
| [src/applicationWorkspace.ts:195](../../../job-tracker-ui/src/applicationWorkspace.ts#L195) | GET | `/jobapplications/${jobId}/match` |
|
||||
| [src/applicationWorkspace.ts:279](../../../job-tracker-ui/src/applicationWorkspace.ts#L279) | GET | `/jobapplications/${jobId}/cv` |
|
||||
| [src/applicationWorkspace.ts:281](../../../job-tracker-ui/src/applicationWorkspace.ts#L281) | PUT | `/jobapplications/${jobId}/cv` |
|
||||
| [src/applicationWorkspace.ts:283](../../../job-tracker-ui/src/applicationWorkspace.ts#L283) | GET | `/jobapplications/${jobId}/tailoring` |
|
||||
| [src/applicationWorkspace.ts:285](../../../job-tracker-ui/src/applicationWorkspace.ts#L285) | GET | `/jobapplications/${jobId}/cover-letter` |
|
||||
| [src/applicationWorkspace.ts:287](../../../job-tracker-ui/src/applicationWorkspace.ts#L287) | PUT | `/jobapplications/${jobId}/cover-letter` |
|
||||
| [src/applicationWorkspace.ts:289](../../../job-tracker-ui/src/applicationWorkspace.ts#L289) | POST | `/jobapplications/${jobId}/cover-letter/versions/${version}/restore` |
|
||||
| [src/applicationWorkspace.ts:291](../../../job-tracker-ui/src/applicationWorkspace.ts#L291) | GET | `/jobapplications/${jobId}/submitted-packages` |
|
||||
| [src/applicationWorkspace.ts:293](../../../job-tracker-ui/src/applicationWorkspace.ts#L293) | POST | `/jobapplications/${jobId}/submitted-packages` |
|
||||
| [src/applicationWorkspace.ts:295](../../../job-tracker-ui/src/applicationWorkspace.ts#L295) | GET | `/jobapplications/${jobId}/submitted-packages/${packageId}` |
|
||||
| [src/applicationWorkspace.ts:297](../../../job-tracker-ui/src/applicationWorkspace.ts#L297) | GET | `/jobapplications/${jobId}/submitted-packages/${packageId}/attachments/${attachmentId}` |
|
||||
| [src/applicationWorkspace.ts:299](../../../job-tracker-ui/src/applicationWorkspace.ts#L299) | PUT | `/jobapplications/${jobId}/application-drafts` |
|
||||
| [src/applicationWorkspace.ts:345](../../../job-tracker-ui/src/applicationWorkspace.ts#L345) | GET | `/jobapplications/${jobId}/interview-prep` |
|
||||
| [src/applicationWorkspace.ts:347](../../../job-tracker-ui/src/applicationWorkspace.ts#L347) | POST | `/jobapplications/${jobId}/interview-prep` |
|
||||
| [src/applicationWorkspace.ts:349](../../../job-tracker-ui/src/applicationWorkspace.ts#L349) | PATCH | `/jobapplications/${jobId}/interview-prep/${itemId}` |
|
||||
| [src/applicationWorkspace.ts:351](../../../job-tracker-ui/src/applicationWorkspace.ts#L351) | DELETE | `/jobapplications/${jobId}/interview-prep/${itemId}` |
|
||||
| [src/applicationWorkspace.ts:353](../../../job-tracker-ui/src/applicationWorkspace.ts#L353) | GET | `/jobapplications/${jobId}/follow-up` |
|
||||
| [src/applicationWorkspace.ts:355](../../../job-tracker-ui/src/applicationWorkspace.ts#L355) | PUT | `/jobapplications/${jobId}/follow-up` |
|
||||
| [src/applicationWorkspace.ts:360](../../../job-tracker-ui/src/applicationWorkspace.ts#L360) | GET | `/jobapplications/${jobId}/checklist` |
|
||||
| [src/applicationWorkspace.ts:362](../../../job-tracker-ui/src/applicationWorkspace.ts#L362) | POST | `/jobapplications/${jobId}/checklist` |
|
||||
| [src/applicationWorkspace.ts:364](../../../job-tracker-ui/src/applicationWorkspace.ts#L364) | PATCH | `/jobapplications/${jobId}/checklist/${itemId}` |
|
||||
| [src/applicationWorkspace.ts:366](../../../job-tracker-ui/src/applicationWorkspace.ts#L366) | DELETE | `/jobapplications/${jobId}/checklist/${itemId}` |
|
||||
| [src/applicationWorkspace.ts:368](../../../job-tracker-ui/src/applicationWorkspace.ts#L368) | PUT | `/jobapplications/${jobId}/checklist/order` |
|
||||
| [src/components/AddJobModal.tsx:224](../../../job-tracker-ui/src/components/AddJobModal.tsx#L224) | GET | "/jobapplications/duplicate-check" |
|
||||
| [src/components/AddJobModal.tsx:247](../../../job-tracker-ui/src/components/AddJobModal.tsx#L247) | POST | "/companies" |
|
||||
| [src/components/AddJobModal.tsx:271](../../../job-tracker-ui/src/components/AddJobModal.tsx#L271) | POST | "/jobimport/preview" |
|
||||
| [src/components/AddJobModal.tsx:312](../../../job-tracker-ui/src/components/AddJobModal.tsx#L312) | POST | "/attachments" |
|
||||
| [src/components/AddJobModal.tsx:331](../../../job-tracker-ui/src/components/AddJobModal.tsx#L331) | POST | "/jobapplications" |
|
||||
| [src/components/AddJobModal.tsx:358](../../../job-tracker-ui/src/components/AddJobModal.tsx#L358) | POST | `/jobapplications/${response.data.id}/generate-tailored-cv-draft` |
|
||||
| [src/components/AiPrivacySettingsCard.tsx:24](../../../job-tracker-ui/src/components/AiPrivacySettingsCard.tsx#L24) | GET | "/ai/settings" |
|
||||
| [src/components/AiPrivacySettingsCard.tsx:35](../../../job-tracker-ui/src/components/AiPrivacySettingsCard.tsx#L35) | PUT | "/ai/settings" |
|
||||
| [src/components/AiUsageCard.tsx:33](../../../job-tracker-ui/src/components/AiUsageCard.tsx#L33) | GET | "/ai/usage" |
|
||||
| [src/components/AiUsageCard.tsx:36](../../../job-tracker-ui/src/components/AiUsageCard.tsx#L36) | GET | "/billing/status" |
|
||||
| [src/components/AiUsageCard.tsx:46](../../../job-tracker-ui/src/components/AiUsageCard.tsx#L46) | POST | `/billing/${path}` |
|
||||
| [src/components/ApplicationCalendarActions.tsx:23](../../../job-tracker-ui/src/components/ApplicationCalendarActions.tsx#L23) | GET | "/calendar/status" |
|
||||
| [src/components/ApplicationCalendarActions.tsx:32](../../../job-tracker-ui/src/components/ApplicationCalendarActions.tsx#L32) | POST | `/calendar/jobs/${jobId}/events` |
|
||||
| [src/components/ApplicationCalendarActions.tsx:41](../../../job-tracker-ui/src/components/ApplicationCalendarActions.tsx#L41) | GET | `/calendar/jobs/${jobId}/events.ics` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:23](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L23) | GET | `/jobapplications/${jobId}/status-suggestion` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:34](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L34) | PATCH | `/jobapplications/${jobId}/status` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:69](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L69) | GET | `/jobapplications/${jobId}/focus-plan` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:81](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L81) | GET | `/jobapplications/${jobId}/focus-plan/operation` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:91](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L91) | GET | `/operations/${operation.id}` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:113](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L113) | POST | `/jobapplications/${jobId}/focus-plan/operations` |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:128](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L128) | POST | `/operations/${operation.id}/${action}` |
|
||||
| [src/components/Attachment.tsx:15](../../../job-tracker-ui/src/components/Attachment.tsx#L15) | POST | "/attachments" |
|
||||
| [src/components/Attachments.tsx:98](../../../job-tracker-ui/src/components/Attachments.tsx#L98) | GET | `/attachments/${jobId}` |
|
||||
| [src/components/Attachments.tsx:125](../../../job-tracker-ui/src/components/Attachments.tsx#L125) | POST | "/attachments" |
|
||||
| [src/components/Attachments.tsx:143](../../../job-tracker-ui/src/components/Attachments.tsx#L143) | PATCH | `/attachments/${a.id}` |
|
||||
| [src/components/Attachments.tsx:153](../../../job-tracker-ui/src/components/Attachments.tsx#L153) | PATCH | `/attachments/${a.id}` |
|
||||
| [src/components/Attachments.tsx:164](../../../job-tracker-ui/src/components/Attachments.tsx#L164) | DELETE | `/attachments/${a.id}` |
|
||||
| [src/components/Attachments.tsx:179](../../../job-tracker-ui/src/components/Attachments.tsx#L179) | GET | `/attachments/download/${id}` |
|
||||
| [src/components/AuthStatusCard.tsx:32](../../../job-tracker-ui/src/components/AuthStatusCard.tsx#L32) | GET | "/auth/me" |
|
||||
| [src/components/AuthStatusCard.tsx:73](../../../job-tracker-ui/src/components/AuthStatusCard.tsx#L73) | POST | "/auth/logout" |
|
||||
| [src/components/BackupCard.tsx:28](../../../job-tracker-ui/src/components/BackupCard.tsx#L28) | GET | "/account-lifecycle/status" |
|
||||
| [src/components/BackupCard.tsx:49](../../../job-tracker-ui/src/components/BackupCard.tsx#L49) | POST | "/export/account" |
|
||||
| [src/components/BackupCard.tsx:62](../../../job-tracker-ui/src/components/BackupCard.tsx#L62) | POST | "/backup/encrypted" |
|
||||
| [src/components/BackupCard.tsx:87](../../../job-tracker-ui/src/components/BackupCard.tsx#L87) | POST | "/account-lifecycle/delete" |
|
||||
| [src/components/CompaniesTable.tsx:57](../../../job-tracker-ui/src/components/CompaniesTable.tsx#L57) | GET | "/companies" |
|
||||
| [src/components/CompaniesTable.tsx:94](../../../job-tracker-ui/src/components/CompaniesTable.tsx#L94) | GET | `/companies/${company.id}/relationship` |
|
||||
| [src/components/CompaniesTable.tsx:108](../../../job-tracker-ui/src/components/CompaniesTable.tsx#L108) | PUT | `/companies/${editing.id}` |
|
||||
| [src/components/Correspondence.tsx:157](../../../job-tracker-ui/src/components/Correspondence.tsx#L157) | GET | `/correspondence/${jobId}` |
|
||||
| [src/components/Correspondence.tsx:164](../../../job-tracker-ui/src/components/Correspondence.tsx#L164) | GET | "/gmail/status" |
|
||||
| [src/components/Correspondence.tsx:176](../../../job-tracker-ui/src/components/Correspondence.tsx#L176) | GET | "/gmail/job-candidates" |
|
||||
| [src/components/Correspondence.tsx:194](../../../job-tracker-ui/src/components/Correspondence.tsx#L194) | GET | "/jobapplications/choices" |
|
||||
| [src/components/Correspondence.tsx:213](../../../job-tracker-ui/src/components/Correspondence.tsx#L213) | POST | "/gmail/refresh-linked-threads" |
|
||||
| [src/components/Correspondence.tsx:311](../../../job-tracker-ui/src/components/Correspondence.tsx#L311) | POST | "/correspondence" |
|
||||
| [src/components/Correspondence.tsx:327](../../../job-tracker-ui/src/components/Correspondence.tsx#L327) | POST | "/correspondence" |
|
||||
| [src/components/Correspondence.tsx:348](../../../job-tracker-ui/src/components/Correspondence.tsx#L348) | GET | "/gmail/connect-url" |
|
||||
| [src/components/Correspondence.tsx:358](../../../job-tracker-ui/src/components/Correspondence.tsx#L358) | DELETE | "/gmail/connection" |
|
||||
| [src/components/Correspondence.tsx:371](../../../job-tracker-ui/src/components/Correspondence.tsx#L371) | DELETE | `/correspondence/${messageId}` |
|
||||
| [src/components/Correspondence.tsx:382](../../../job-tracker-ui/src/components/Correspondence.tsx#L382) | POST | "/gmail/import" |
|
||||
| [src/components/Correspondence.tsx:400](../../../job-tracker-ui/src/components/Correspondence.tsx#L400) | POST | "/gmail/import-thread" |
|
||||
| [src/components/Correspondence.tsx:422](../../../job-tracker-ui/src/components/Correspondence.tsx#L422) | POST | "/gmail/unlink-thread" |
|
||||
| [src/components/Correspondence.tsx:443](../../../job-tracker-ui/src/components/Correspondence.tsx#L443) | POST | "/gmail/relink-thread" |
|
||||
| [src/components/DashboardView.tsx:133](../../../job-tracker-ui/src/components/DashboardView.tsx#L133) | GET | "/jobapplications/stats" |
|
||||
| [src/components/DashboardView.tsx:134](../../../job-tracker-ui/src/components/DashboardView.tsx#L134) | GET | "/jobapplications/analytics-overview" |
|
||||
| [src/components/DashboardView.tsx:135](../../../job-tracker-ui/src/components/DashboardView.tsx#L135) | GET | "/jobapplications/reminders" |
|
||||
| [src/components/DashboardView.tsx:157](../../../job-tracker-ui/src/components/DashboardView.tsx#L157) | GET | "/jobapplications/analytics" |
|
||||
| [src/components/DashboardView.tsx:158](../../../job-tracker-ui/src/components/DashboardView.tsx#L158) | GET | "/jobapplications/tags" |
|
||||
| [src/components/DashboardView.tsx:159](../../../job-tracker-ui/src/components/DashboardView.tsx#L159) | GET | "/jobapplications/tag-trends" |
|
||||
| [src/components/EditJobDialog.tsx:108](../../../job-tracker-ui/src/components/EditJobDialog.tsx#L108) | GET | `/jobapplications/${jobId}` |
|
||||
| [src/components/EditJobDialog.tsx:147](../../../job-tracker-ui/src/components/EditJobDialog.tsx#L147) | PUT | `/jobapplications/${jobId}` |
|
||||
| [src/components/EmailProviderConnections.tsx:28](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L28) | GET | "/gmail/status" |
|
||||
| [src/components/EmailProviderConnections.tsx:37](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L37) | GET | "/microsoft-graph/status" |
|
||||
| [src/components/EmailProviderConnections.tsx:46](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L46) | GET | "/imap/status" |
|
||||
| [src/components/EmailProviderConnections.tsx:85](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L85) | GET | connectUrlPath |
|
||||
| [src/components/EmailProviderConnections.tsx:95](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L95) | DELETE | path |
|
||||
| [src/components/EmailProviderConnections.tsx:110](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L110) | POST | "/imap/connect" |
|
||||
| [src/components/ErrorBoundary.tsx:30](../../../job-tracker-ui/src/components/ErrorBoundary.tsx#L30) | POST | "/client-errors" |
|
||||
| [src/components/GoogleAuthCard.tsx:98](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L98) | GET | "/auth/me" |
|
||||
| [src/components/GoogleAuthCard.tsx:108](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L108) | GET | "/auth/config" |
|
||||
| [src/components/GoogleAuthCard.tsx:140](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L140) | POST | "/auth/google/link" |
|
||||
| [src/components/GoogleAuthCard.tsx:144](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L144) | POST | "/auth/google/exchange" |
|
||||
| [src/components/GoogleAuthCard.tsx:259](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L259) | POST | "/auth/logout" |
|
||||
| [src/components/GoogleAuthCard.tsx:277](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L277) | DELETE | "/auth/google/link" |
|
||||
| [src/components/ImportExportJobs.tsx:187](../../../job-tracker-ui/src/components/ImportExportJobs.tsx#L187) | GET | url |
|
||||
| [src/components/ImportExportJobs.tsx:208](../../../job-tracker-ui/src/components/ImportExportJobs.tsx#L208) | POST | "/companies" |
|
||||
| [src/components/ImportExportJobs.tsx:210](../../../job-tracker-ui/src/components/ImportExportJobs.tsx#L210) | POST | "/jobapplications" |
|
||||
| [src/components/JobTable.tsx:313](../../../job-tracker-ui/src/components/JobTable.tsx#L313) | GET | "/jobapplications" |
|
||||
| [src/components/JobTable.tsx:380](../../../job-tracker-ui/src/components/JobTable.tsx#L380) | DELETE | `/jobapplications/${job.id}` |
|
||||
| [src/components/JobTable.tsx:390](../../../job-tracker-ui/src/components/JobTable.tsx#L390) | POST | `/jobapplications/${id}/restore` |
|
||||
| [src/components/JobTable.tsx:400](../../../job-tracker-ui/src/components/JobTable.tsx#L400) | PATCH | `/jobapplications/${id}/status` |
|
||||
| [src/components/JobTable.tsx:414](../../../job-tracker-ui/src/components/JobTable.tsx#L414) | DELETE | `/jobapplications/${id}` |
|
||||
| [src/components/JobTable.tsx:415](../../../job-tracker-ui/src/components/JobTable.tsx#L415) | POST | `/jobapplications/${id}/restore` |
|
||||
| [src/components/JobTable.tsx:416](../../../job-tracker-ui/src/components/JobTable.tsx#L416) | PATCH | `/jobapplications/${id}/status` |
|
||||
| [src/components/KanbanBoard.tsx:100](../../../job-tracker-ui/src/components/KanbanBoard.tsx#L100) | GET | "/jobapplications/board" |
|
||||
| [src/components/KanbanBoard.tsx:144](../../../job-tracker-ui/src/components/KanbanBoard.tsx#L144) | PATCH | `/jobapplications/${movingJobId}/status` |
|
||||
| [src/components/KanbanBoard.tsx:156](../../../job-tracker-ui/src/components/KanbanBoard.tsx#L156) | PATCH | `/jobapplications/${id}/status` |
|
||||
| [src/components/MicrosoftAuthCard.tsx:54](../../../job-tracker-ui/src/components/MicrosoftAuthCard.tsx#L54) | GET | "/auth/me" |
|
||||
| [src/components/MicrosoftAuthCard.tsx:84](../../../job-tracker-ui/src/components/MicrosoftAuthCard.tsx#L84) | POST | "/auth/microsoft/link" |
|
||||
| [src/components/MicrosoftAuthCard.tsx:91](../../../job-tracker-ui/src/components/MicrosoftAuthCard.tsx#L91) | POST | "/auth/microsoft/exchange" |
|
||||
| [src/components/MicrosoftAuthCard.tsx:202](../../../job-tracker-ui/src/components/MicrosoftAuthCard.tsx#L202) | POST | "/auth/logout" |
|
||||
| [src/components/MicrosoftAuthCard.tsx:220](../../../job-tracker-ui/src/components/MicrosoftAuthCard.tsx#L220) | DELETE | "/auth/microsoft/link" |
|
||||
| [src/components/NotificationsPopover.tsx:41](../../../job-tracker-ui/src/components/NotificationsPopover.tsx#L41) | GET | "/notifications?limit=10" |
|
||||
| [src/components/NotificationsPopover.tsx:59](../../../job-tracker-ui/src/components/NotificationsPopover.tsx#L59) | POST | `/notifications/${notification.id}/read` |
|
||||
| [src/components/NotificationsPopover.tsx:76](../../../job-tracker-ui/src/components/NotificationsPopover.tsx#L76) | DELETE | `/notifications/${notification.id}` |
|
||||
| [src/components/OnboardingChecklist.tsx:47](../../../job-tracker-ui/src/components/OnboardingChecklist.tsx#L47) | GET | "/auth/me" |
|
||||
| [src/components/OnboardingChecklist.tsx:48](../../../job-tracker-ui/src/components/OnboardingChecklist.tsx#L48) | GET | "/career/profile" |
|
||||
| [src/components/OnboardingChecklist.tsx:50](../../../job-tracker-ui/src/components/OnboardingChecklist.tsx#L50) | GET | url |
|
||||
| [src/components/QuickCommandDialog.tsx:69](../../../job-tracker-ui/src/components/QuickCommandDialog.tsx#L69) | GET | "/jobapplications" |
|
||||
| [src/components/QuickCommandDialog.tsx:73](../../../job-tracker-ui/src/components/QuickCommandDialog.tsx#L73) | GET | "/companies" |
|
||||
| [src/components/RemindersView.tsx:78](../../../job-tracker-ui/src/components/RemindersView.tsx#L78) | GET | "/jobapplications/reminders" |
|
||||
| [src/components/RemindersView.tsx:98](../../../job-tracker-ui/src/components/RemindersView.tsx#L98) | PATCH | `/jobapplications/${id}/followup` |
|
||||
| [src/components/RulesSettingsCard.tsx:27](../../../job-tracker-ui/src/components/RulesSettingsCard.tsx#L27) | GET | "/rules" |
|
||||
| [src/components/RulesSettingsCard.tsx:42](../../../job-tracker-ui/src/components/RulesSettingsCard.tsx#L42) | PUT | "/rules" |
|
||||
| [src/components/SessionsSettingsCard.tsx:49](../../../job-tracker-ui/src/components/SessionsSettingsCard.tsx#L49) | GET | "/auth/sessions" |
|
||||
| [src/components/SessionsSettingsCard.tsx:60](../../../job-tracker-ui/src/components/SessionsSettingsCard.tsx#L60) | DELETE | `/auth/sessions/${id}` |
|
||||
| [src/components/SessionsSettingsCard.tsx:77](../../../job-tracker-ui/src/components/SessionsSettingsCard.tsx#L77) | POST | "/auth/sessions/revoke-others" |
|
||||
| [src/components/SettingsView.tsx:80](../../../job-tracker-ui/src/components/SettingsView.tsx#L80) | GET | "/notification-settings" |
|
||||
| [src/components/SettingsView.tsx:91](../../../job-tracker-ui/src/components/SettingsView.tsx#L91) | PUT | "/notification-settings" |
|
||||
| [src/components/TwoFactorChallenge.tsx:29](../../../job-tracker-ui/src/components/TwoFactorChallenge.tsx#L29) | POST | "/auth/2fa/challenge" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:73](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L73) | GET | "/auth/2fa/status" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:79](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L79) | GET | "/auth/2fa/trusted-devices" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:90](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L90) | DELETE | `/auth/2fa/trusted-devices/${id}` |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:99](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L99) | POST | "/auth/2fa/trusted-devices/revoke-all" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:123](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L123) | POST | "/auth/2fa/setup" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:128](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L128) | POST | "/auth/2fa/disable" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:133](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L133) | POST | "/auth/2fa/recovery-codes/regenerate" |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:149](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L149) | POST | "/auth/2fa/verify-setup" |
|
||||
| [src/components/UserManagementCard.tsx:34](../../../job-tracker-ui/src/components/UserManagementCard.tsx#L34) | GET | "/users" |
|
||||
| [src/components/UserManagementCard.tsx:98](../../../job-tracker-ui/src/components/UserManagementCard.tsx#L98) | POST | "/users" |
|
||||
| [src/components/UserManagementCard.tsx:152](../../../job-tracker-ui/src/components/UserManagementCard.tsx#L152) | DELETE | `/users/${u.id}` |
|
||||
| [src/components/UserManagementCard.tsx:167](../../../job-tracker-ui/src/components/UserManagementCard.tsx#L167) | POST | `/users/${u.id}/send-password-reset` |
|
||||
| [src/components/job-workspace/useJobWorkspaceBaseData.ts:51](../../../job-tracker-ui/src/components/job-workspace/useJobWorkspaceBaseData.ts#L51) | GET | `/jobapplications/${jobId}` |
|
||||
| [src/components/job-workspace/useJobWorkspaceBaseData.ts:64](../../../job-tracker-ui/src/components/job-workspace/useJobWorkspaceBaseData.ts#L64) | GET | `/attachments/${jobId}` |
|
||||
| [src/components/job-workspace/useJobWorkspaceBaseData.ts:74](../../../job-tracker-ui/src/components/job-workspace/useJobWorkspaceBaseData.ts#L74) | GET | `/auth/me` |
|
||||
| [src/components/job-workspace/useJobWorkspaceBaseData.ts:82](../../../job-tracker-ui/src/components/job-workspace/useJobWorkspaceBaseData.ts#L82) | GET | `/jobapplications/${jobId}/history` |
|
||||
| [src/cvBuilder.ts:265](../../../job-tracker-ui/src/cvBuilder.ts#L265) | GET | "/cv/themes" |
|
||||
| [src/cvBuilder.ts:266](../../../job-tracker-ui/src/cvBuilder.ts#L266) | GET | `/cv/themes/${encodeURIComponent(themeId)}/preview` |
|
||||
| [src/cvBuilder.ts:267](../../../job-tracker-ui/src/cvBuilder.ts#L267) | GET | "/cv/outline" |
|
||||
| [src/cvBuilder.ts:268](../../../job-tracker-ui/src/cvBuilder.ts#L268) | GET | "/cv/variants" |
|
||||
| [src/cvBuilder.ts:270](../../../job-tracker-ui/src/cvBuilder.ts#L270) | POST | "/cv/variants" |
|
||||
| [src/cvBuilder.ts:271](../../../job-tracker-ui/src/cvBuilder.ts#L271) | GET | `/cv/variants/${id}` |
|
||||
| [src/cvBuilder.ts:273](../../../job-tracker-ui/src/cvBuilder.ts#L273) | PUT | `/cv/variants/${id}` |
|
||||
| [src/cvBuilder.ts:274](../../../job-tracker-ui/src/cvBuilder.ts#L274) | DELETE | `/cv/variants/${id}` |
|
||||
| [src/cvBuilder.ts:275](../../../job-tracker-ui/src/cvBuilder.ts#L275) | POST | `/cv/variants/${id}/duplicate` |
|
||||
| [src/cvBuilder.ts:276](../../../job-tracker-ui/src/cvBuilder.ts#L276) | PUT | `/cv/variants/${id}/public` |
|
||||
| [src/cvBuilder.ts:277](../../../job-tracker-ui/src/cvBuilder.ts#L277) | GET | `/cv/variants/${id}/versions` |
|
||||
| [src/cvBuilder.ts:278](../../../job-tracker-ui/src/cvBuilder.ts#L278) | POST | `/cv/variants/${id}/versions/${version}/restore` |
|
||||
| [src/cvBuilder.ts:279](../../../job-tracker-ui/src/cvBuilder.ts#L279) | POST | "/cv/preview" |
|
||||
| [src/cvBuilder.ts:281](../../../job-tracker-ui/src/cvBuilder.ts#L281) | POST | "/cv/ai/assist" |
|
||||
| [src/hooks/useCompanies.ts:31](../../../job-tracker-ui/src/hooks/useCompanies.ts#L31) | GET | '/companies' |
|
||||
| [src/i18n/I18nProvider.tsx:35](../../../job-tracker-ui/src/i18n/I18nProvider.tsx#L35) | PUT | "/auth/preferences/language" |
|
||||
| [src/views/AdminAuditPage.tsx:49](../../../job-tracker-ui/src/views/AdminAuditPage.tsx#L49) | GET | "/admin/audit?take=200" |
|
||||
| [src/views/AdminAuditPage.tsx:59](../../../job-tracker-ui/src/views/AdminAuditPage.tsx#L59) | POST | `/admin/audit/${e.id}/undo` |
|
||||
| [src/views/AdminAuditPage.tsx:73](../../../job-tracker-ui/src/views/AdminAuditPage.tsx#L73) | POST | `/jobapplications/${e.jobApplicationId}/restore` |
|
||||
| [src/views/AdminSystemPage.tsx:241](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L241) | GET | "/admin/system" |
|
||||
| [src/views/AdminSystemPage.tsx:242](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L242) | GET | "/admin/system/email-settings" |
|
||||
| [src/views/AdminSystemPage.tsx:243](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L243) | GET | "/admin/system/cv-benchmark" |
|
||||
| [src/views/AdminSystemPage.tsx:244](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L244) | GET | "/admin/system/maintenance-jobs" |
|
||||
| [src/views/AdminSystemPage.tsx:313](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L313) | POST | "/users/send-test-email" |
|
||||
| [src/views/AdminSystemPage.tsx:330](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L330) | PUT | "/admin/system/email-settings" |
|
||||
| [src/views/AdminSystemPage.tsx:358](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L358) | POST | `/admin/system/maintenance-jobs/${encodeURIComponent(jobId)}/runs` |
|
||||
| [src/views/AdminSystemPage.tsx:381](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L381) | POST | "/admin/system/ai/probe" |
|
||||
| [src/views/AdminUsersPage.tsx:49](../../../job-tracker-ui/src/views/AdminUsersPage.tsx#L49) | GET | "/users" |
|
||||
| [src/views/AdminUsersPage.tsx:93](../../../job-tracker-ui/src/views/AdminUsersPage.tsx#L93) | PUT | `/users/${u.id}/roles` |
|
||||
| [src/views/AdminUsersPage.tsx:103](../../../job-tracker-ui/src/views/AdminUsersPage.tsx#L103) | POST | `/users/${u.id}/send-password-reset` |
|
||||
| [src/views/AdminUsersPage.tsx:117](../../../job-tracker-ui/src/views/AdminUsersPage.tsx#L117) | DELETE | `/users/${u.id}` |
|
||||
| [src/views/AdminUsersPage.tsx:215](../../../job-tracker-ui/src/views/AdminUsersPage.tsx#L215) | POST | "/users" |
|
||||
| [src/views/CareerProfilePage.tsx:185](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L185) | GET | "/career/profile/versions" |
|
||||
| [src/views/CareerProfilePage.tsx:195](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L195) | POST | `/career/profile/versions/${version}/restore` |
|
||||
| [src/views/CareerProfilePage.tsx:220](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L220) | GET | "/profile-cv/runs" |
|
||||
| [src/views/CareerProfilePage.tsx:232](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L232) | POST | "/profile-cv/upload" |
|
||||
| [src/views/CareerProfilePage.tsx:248](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L248) | GET | "/career/profile" |
|
||||
| [src/views/CareerProfilePage.tsx:249](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L249) | GET | "/auth/me" |
|
||||
| [src/views/CareerProfilePage.tsx:289](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L289) | GET | `/profile-cv/runs/${run.id}/diff` |
|
||||
| [src/views/CareerProfilePage.tsx:408](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L408) | POST | "/auth/avatar" |
|
||||
| [src/views/CareerProfilePage.tsx:495](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L495) | DELETE | "/auth/avatar" |
|
||||
| [src/views/CareerProfilePage.tsx:556](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L556) | POST | "/profile-cv/rebuild" |
|
||||
| [src/views/CareerProfilePage.tsx:574](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L574) | POST | "/profile-cv/improve" |
|
||||
| [src/views/CareerProfilePage.tsx:592](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L592) | POST | "/profile-cv/reprocess" |
|
||||
| [src/views/CareerProfilePage.tsx:669](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L669) | POST | `/operations/${run.operation!.id}/cancel` |
|
||||
| [src/views/CareerProfilePage.tsx:680](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L680) | POST | `/operations/${run.operation!.id}/retry` |
|
||||
| [src/views/CareerProfilePage.tsx:726](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L726) | POST | `/profile-cv/runs/${run.id}/accept` |
|
||||
| [src/views/CareerProfilePage.tsx:737](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L737) | POST | `/profile-cv/runs/${run.id}/discard` |
|
||||
| [src/views/CareerProfilePage.tsx:772](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L772) | POST | "/profile-cv/parse" |
|
||||
| [src/views/CareerProfilePage.tsx:855](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L855) | PUT | "/career/profile" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:158](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L158) | GET | "/correspondence/page" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:185](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L185) | GET | "/email/providers" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:200](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L200) | GET | "/jobapplications/choices" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:213](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L213) | GET | "/email/drafts" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:248](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L248) | GET | "/email/message" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:260](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L260) | GET | `/correspondence/message/${item.id}` |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:375](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L375) | DELETE | `/email/drafts/${draft.id}` |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:394](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L394) | PUT | `/email/drafts/${draft.id}` |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:400](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L400) | POST | "/email/drafts" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:432](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L432) | POST | "/email/send" |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:447](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L447) | DELETE | `/email/drafts/${draft.id}` |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:476](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L476) | POST | `/email/drafts/${draft.id}/new-attempt` |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:503](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L503) | POST | "/gmail/unlink-thread" |
|
||||
| [src/views/CvBuilderEditor.tsx:312](../../../job-tracker-ui/src/views/CvBuilderEditor.tsx#L312) | POST | cvBuilderApi.exportPdfUrl(variantId) |
|
||||
| [src/views/CvBuilderPage.tsx:112](../../../job-tracker-ui/src/views/CvBuilderPage.tsx#L112) | POST | cvBuilderApi.exportPdfUrl(id) |
|
||||
| [src/views/ForgotPasswordPage.tsx:62](../../../job-tracker-ui/src/views/ForgotPasswordPage.tsx#L62) | POST | "/auth/request-password-reset" |
|
||||
| [src/views/GmailReviewPage.tsx:35](../../../job-tracker-ui/src/views/GmailReviewPage.tsx#L35) | GET | "/gmail/review-candidates" |
|
||||
| [src/views/GmailReviewPage.tsx:36](../../../job-tracker-ui/src/views/GmailReviewPage.tsx#L36) | GET | "/gmail/suggested-jobs" |
|
||||
| [src/views/GmailReviewPage.tsx:61](../../../job-tracker-ui/src/views/GmailReviewPage.tsx#L61) | POST | "/gmail/review-decision" |
|
||||
| [src/views/GmailReviewPage.tsx:88](../../../job-tracker-ui/src/views/GmailReviewPage.tsx#L88) | POST | "/gmail/manual-sync" |
|
||||
| [src/views/GmailReviewPage.tsx:112](../../../job-tracker-ui/src/views/GmailReviewPage.tsx#L112) | POST | "/gmail/create-suggested-job" |
|
||||
| [src/views/JobDiscoveryPage.tsx:54](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L54) | GET | "/job-discovery/saved-searches" |
|
||||
| [src/views/JobDiscoveryPage.tsx:63](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L63) | GET | "/job-discovery/search" |
|
||||
| [src/views/JobDiscoveryPage.tsx:78](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L78) | POST | "/job-discovery/saved-searches" |
|
||||
| [src/views/JobDiscoveryPage.tsx:89](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L89) | POST | `/job-discovery/saved-searches/${saved.id}/run` |
|
||||
| [src/views/JobDiscoveryPage.tsx:100](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L100) | DELETE | `/job-discovery/saved-searches/${saved.id}` |
|
||||
| [src/views/JobDiscoveryPage.tsx:109](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L109) | PATCH | `/job-discovery/saved-searches/${saved.id}` |
|
||||
| [src/views/JobDiscoveryPage.tsx:118](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L118) | PATCH | `/job-discovery/saved-searches/${activeSavedSearchId}/results/${encodeURIComponent(jobId)}/dismiss` |
|
||||
| [src/views/LandingPage.tsx:51](../../../job-tracker-ui/src/views/LandingPage.tsx#L51) | GET | "/auth/me" |
|
||||
| [src/views/LoginPage.tsx:59](../../../job-tracker-ui/src/views/LoginPage.tsx#L59) | GET | "/auth/config" |
|
||||
| [src/views/LoginPage.tsx:67](../../../job-tracker-ui/src/views/LoginPage.tsx#L67) | GET | "/auth/me" |
|
||||
| [src/views/LoginPage.tsx:96](../../../job-tracker-ui/src/views/LoginPage.tsx#L96) | POST | url |
|
||||
| [src/views/LoginPage.tsx:121](../../../job-tracker-ui/src/views/LoginPage.tsx#L121) | POST | "/auth/resend-verification-email" |
|
||||
| [src/views/MicrosoftLegacyRelinkPage.tsx:32](../../../job-tracker-ui/src/views/MicrosoftLegacyRelinkPage.tsx#L32) | POST | "/auth/microsoft/legacy-relink/confirm" |
|
||||
| [src/views/OfferComparisonPage.tsx:14](../../../job-tracker-ui/src/views/OfferComparisonPage.tsx#L14) | GET | "/jobapplications" |
|
||||
| [src/views/OperationsPage.tsx:47](../../../job-tracker-ui/src/views/OperationsPage.tsx#L47) | GET | "/operations?limit=50" |
|
||||
| [src/views/OperationsPage.tsx:48](../../../job-tracker-ui/src/views/OperationsPage.tsx#L48) | GET | "/notifications?limit=50" |
|
||||
| [src/views/OperationsPage.tsx:101](../../../job-tracker-ui/src/views/OperationsPage.tsx#L101) | POST | `/notifications/${notification.id}/read` |
|
||||
| [src/views/OperationsPage.tsx:105](../../../job-tracker-ui/src/views/OperationsPage.tsx#L105) | DELETE | `/notifications/${notification.id}` |
|
||||
| [src/views/OperationsPage.tsx:131](../../../job-tracker-ui/src/views/OperationsPage.tsx#L131) | POST | `/operations/${operation.id}/cancel` |
|
||||
| [src/views/OperationsPage.tsx:136](../../../job-tracker-ui/src/views/OperationsPage.tsx#L136) | POST | `/operations/${operation.id}/retry` |
|
||||
| [src/views/ProfilePage.tsx:91](../../../job-tracker-ui/src/views/ProfilePage.tsx#L91) | GET | "/auth/me" |
|
||||
| [src/views/ProfilePage.tsx:103](../../../job-tracker-ui/src/views/ProfilePage.tsx#L103) | GET | "/auth/email-change" |
|
||||
| [src/views/ProfilePage.tsx:149](../../../job-tracker-ui/src/views/ProfilePage.tsx#L149) | POST | "/auth/avatar" |
|
||||
| [src/views/ProfilePage.tsx:202](../../../job-tracker-ui/src/views/ProfilePage.tsx#L202) | DELETE | "/auth/avatar" |
|
||||
| [src/views/ProfilePage.tsx:272](../../../job-tracker-ui/src/views/ProfilePage.tsx#L272) | POST | "/auth/email-change/request" |
|
||||
| [src/views/ProfilePage.tsx:290](../../../job-tracker-ui/src/views/ProfilePage.tsx#L290) | POST | "/auth/email-change/cancel" |
|
||||
| [src/views/ProfilePage.tsx:316](../../../job-tracker-ui/src/views/ProfilePage.tsx#L316) | PUT | "/auth/profile" |
|
||||
| [src/views/ProfilePage.tsx:350](../../../job-tracker-ui/src/views/ProfilePage.tsx#L350) | POST | "/auth/change-password" |
|
||||
| [src/views/PublicCvPage.tsx:26](../../../job-tracker-ui/src/views/PublicCvPage.tsx#L26) | GET | `/public-cv/${slug}` |
|
||||
| [src/views/ResetPasswordPage.tsx:66](../../../job-tracker-ui/src/views/ResetPasswordPage.tsx#L66) | POST | "/auth/reset-password" |
|
||||
| [src/views/VerifyEmailPage.tsx:31](../../../job-tracker-ui/src/views/VerifyEmailPage.tsx#L31) | POST | emailChange ? "/auth/email-change/confirm" : "/auth/verify-email" |
|
||||
| [src/views/career/CareerEvidenceBank.tsx:15](../../../job-tracker-ui/src/views/career/CareerEvidenceBank.tsx#L15) | GET | "/career/evidence" |
|
||||
| [src/views/career/CareerEvidenceBank.tsx:17](../../../job-tracker-ui/src/views/career/CareerEvidenceBank.tsx#L17) | POST | "/career/evidence" |
|
||||
| [src/views/career/CareerEvidenceBank.tsx:18](../../../job-tracker-ui/src/views/career/CareerEvidenceBank.tsx#L18) | DELETE | `/career/evidence/${item.id}` |
|
||||
@@ -0,0 +1,97 @@
|
||||
# Component and source inventory
|
||||
|
||||
Every production TSX module under `src` and `app` is listed. Lines are size indicators, not complexity scores. Reachability is relative-import reachability from ClientApp; app entry files are expected to be outside that graph. MUI primitives are dependencies, not missing local components. No unreachable file is approved for deletion.
|
||||
|
||||
| Module | Lines | Client graph | Local direct consumers | Rendered component names |
|
||||
|---|---|---|---|---|
|
||||
| [app/[[...slug]]/ClientShell.tsx:1](../../../job-tracker-ui/app/[[...slug]]/ClientShell.tsx#L1) | 14 | outside graph | page.tsx | ClientApp |
|
||||
| [app/layout.tsx:1](../../../job-tracker-ui/app/layout.tsx#L1) | 42 | outside graph | — | Script |
|
||||
| [app/page.tsx:1](../../../job-tracker-ui/app/page.tsx#L1) | 6 | outside graph | — | ClientShell |
|
||||
| [src/App.tsx:1](../../../job-tracker-ui/src/App.tsx#L1) | 500 | reachable | ClientApp.tsx | AccountCircleIcon, AccountPlanProvider, AddJobModal, AdminAuditPage, AdminSystemPage, AdminUsersPage, AlarmIcon, AppShell, Application, ApplicationWorkspacePage, Box, BusinessIcon, Button, CareerWorkspacePage, CompaniesTable, CompareArrowsIcon, ConfirmProvider, ConnectedAccountsPage, CorrespondenceInboxPage, CvBuilderEditor, CvBuilderPage, DashboardIcon, DashboardView, DeleteOutlineIcon, DescriptionOutlinedIcon, ForgotPasswordPage, I18nProvider, IconButton, JobDiscoveryPage, JobTable, JobTrackerThemeProvider, KanbanBoard, LandingPage, LegacyApplicationRedirect, LoginPage, MailOutlineIcon, MemoryIcon, MicrosoftLegacyRelinkPage, Navigate, NotFoundPage, NotificationsPopover, OfferComparisonPage, OperationsPage, PageLoader, ProfilePage, PromptProvider, PublicCvPage, QuickCommandDialog, RemindersView, ResetPasswordPage, Route, RouteErrorPage, RouterProvider, Routes, SearchIcon, SettingsIcon, SettingsView, Shell, ShieldIcon, Suspense, ThemeAwareShell, ThemeControlsContext.Provider, ToastProvider, Typography, VerifyEmailPage, ViewKanbanIcon, WorkOutlineIcon |
|
||||
| [src/ClientApp.tsx:1](../../../job-tracker-ui/src/ClientApp.tsx#L1) | 21 | reachable | ClientShell.tsx | App, ErrorBoundary, I18nProvider, LocalizationProvider |
|
||||
| [src/ThemeProvider.tsx:1](../../../job-tracker-ui/src/ThemeProvider.tsx#L1) | 26 | reachable | App.tsx | CssBaseline, CssVarsProvider, ThemeModeSynchronizer |
|
||||
| [src/accountPlan.tsx:1](../../../job-tracker-ui/src/accountPlan.tsx#L1) | 21 | reachable | App.tsx, AddJobModal.tsx, ApplicationAssets.tsx, ApplicationWorkflowAssist.tsx, InterviewPrep.tsx, AiSectionAssistant.tsx, CareerProfilePage.tsx, CvBuilderEditor.tsx | AccountPlanContext.Provider |
|
||||
| [src/assets/JobbjaktMark.tsx:1](../../../job-tracker-ui/src/assets/JobbjaktMark.tsx#L1) | 19 | reachable | AppShell.tsx | |
|
||||
| [src/components/AddJobModal.tsx:1](../../../job-tracker-ui/src/components/AddJobModal.tsx#L1) | 652 | reachable | App.tsx | Alert, Autocomplete, Box, Button, Checkbox, Chip, CloseIcon, DatePicker, Dialog, DialogActions, DialogContent, DialogTitle, Divider, FormControlLabel, IconButton, List, ListItem, ListItemText, MenuItem, Step, StepLabel, Stepper, TagsInput, TextField, Typography, UploadFileOutlinedIcon |
|
||||
| [src/components/AiPrivacySettingsCard.tsx:1](../../../job-tracker-ui/src/components/AiPrivacySettingsCard.tsx#L1) | 76 | reachable | SettingsView.tsx | Alert, Box, Button, FormControlLabel, Paper, Skeleton, Switch, Typography |
|
||||
| [src/components/AiUsageCard.tsx:1](../../../job-tracker-ui/src/components/AiUsageCard.tsx#L1) | 91 | reachable | SettingsView.tsx | Alert, Box, Button, LinearProgress, Paper, Skeleton, Stack, Typography |
|
||||
| [src/components/ApplicationAssets.tsx:1](../../../job-tracker-ui/src/components/ApplicationAssets.tsx#L1) | 769 | reachable | ApplicationWorkspacePage.tsx | Alert, ApplicationTailoringSection, ArchiveOutlinedIcon, AutoFixHighIcon, Box, Button, Chip, CoverLetterAiAssistant, Dialog, DialogActions, DialogContent, DialogTitle, Divider, DownloadOutlinedIcon, FormControl, IconButton, InputLabel, MenuItem, OpenInNewIcon, Paper, RestoreIcon, RichTextField, Select, Shell, Skeleton, Stack, SubmittedPackagesSection, TextField, Tooltip, Typography |
|
||||
| [src/components/ApplicationCalendarActions.tsx:1](../../../job-tracker-ui/src/components/ApplicationCalendarActions.tsx#L1) | 81 | reachable | ApplicationWorkspacePage.tsx | Alert, Box, Button, CalendarMonthOutlinedIcon, CircularProgress, DownloadOutlinedIcon, OpenInNewIcon, Stack, Typography |
|
||||
| [src/components/ApplicationChecklist.tsx:1](../../../job-tracker-ui/src/components/ApplicationChecklist.tsx#L1) | 224 | reachable | ApplicationWorkspacePage.tsx | Alert, ArrowDownwardIcon, ArrowUpwardIcon, Box, Button, Checkbox, Chip, DeleteOutlineIcon, IconButton, LinearProgress, Paper, Skeleton, Stack, TextField, Tooltip, Typography |
|
||||
| [src/components/ApplicationIntelligence.tsx:1](../../../job-tracker-ui/src/components/ApplicationIntelligence.tsx#L1) | 380 | reachable | ApplicationWorkspacePage.tsx | Alert, Box, Bullets, Chip, Chips, Divider, LinearProgress, Paper, React.Fragment, SectionShell, Skeleton, Stack, ToggleButton, ToggleButtonGroup, Typography |
|
||||
| [src/components/ApplicationWorkflowAssist.tsx:1](../../../job-tracker-ui/src/components/ApplicationWorkflowAssist.tsx#L1) | 166 | reachable | ApplicationWorkspacePage.tsx | Alert, Box, Button, CircularProgress, DraftCard, ListCard, Paper, Stack, TwoColumnSection, Typography |
|
||||
| [src/components/Attachment.tsx:1](../../../job-tracker-ui/src/components/Attachment.tsx#L1) | 26 | outside graph | — | |
|
||||
| [src/components/Attachments.tsx:1](../../../job-tracker-ui/src/components/Attachments.tsx#L1) | 373 | reachable | ApplicationWorkspacePage.tsx | Alert, Box, Button, Chip, CloudUploadOutlinedIcon, DeleteOutlineIcon, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, DriveFileRenameOutlineIcon, FormControl, IconButton, InputLabel, LinearProgress, MenuItem, Select, Switch, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, VisibilityOutlinedIcon |
|
||||
| [src/components/AuthStatusCard.tsx:1](../../../job-tracker-ui/src/components/AuthStatusCard.tsx#L1) | 88 | reachable | ProfilePage.tsx | Box, Button, Paper, Typography |
|
||||
| [src/components/BackupCard.tsx:1](../../../job-tracker-ui/src/components/BackupCard.tsx#L1) | 138 | reachable | SettingsView.tsx | Alert, Box, Button, Divider, Paper, Typography |
|
||||
| [src/components/CompaniesTable.tsx:1](../../../job-tracker-ui/src/components/CompaniesTable.tsx#L1) | 346 | reachable | App.tsx | Alert, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, EditOutlinedIcon, IconButton, Paper, PeopleAltOutlinedIcon, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, ViewStateNotice |
|
||||
| [src/components/Correspondence.tsx:1](../../../job-tracker-ui/src/components/Correspondence.tsx#L1) | 747 | reachable | ApplicationWorkspacePage.tsx | AutoAwesomeIcon, Autocomplete, Box, Button, Chip, CircularProgress, DeleteOutlineIcon, Dialog, DialogActions, DialogContent, DialogTitle, Divider, IconButton, List, ListItemButton, ListItemText, MailOutlineIcon, Paper, React.Fragment, SearchIcon, Tab, Tabs, TextField, ToggleButton, ToggleButtonGroup, Typography |
|
||||
| [src/components/CropImageDialog.tsx:1](../../../job-tracker-ui/src/components/CropImageDialog.tsx#L1) | 225 | reachable | CareerProfilePage.tsx, ProfilePage.tsx | Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Slider, Typography |
|
||||
| [src/components/CvTemplateGallery.tsx:1](../../../job-tracker-ui/src/components/CvTemplateGallery.tsx#L1) | 57 | reachable | CvCustomizeTab.tsx, CvBuilderPage.tsx | Box, Button, CheckCircleIcon, Chip, CvTemplateThumbnail, Paper, Stack, Typography |
|
||||
| [src/components/CvTemplateThumbnail.tsx:1](../../../job-tracker-ui/src/components/CvTemplateThumbnail.tsx#L1) | 35 | reachable | CvTemplateGallery.tsx, CvBuilderPage.tsx | Box |
|
||||
| [src/components/DashboardView.tsx:1](../../../job-tracker-ui/src/components/DashboardView.tsx#L1) | 682 | reachable | App.tsx | ArrowDownwardIcon, ArrowUpwardIcon, Box, Button, Card, Checkbox, Chip, LinearProgress, Menu, MenuItem, OnboardingChecklist, SectionCard, Stack, TuneIcon, Typography, ViewStateNotice |
|
||||
| [src/components/EditJobDialog.tsx:1](../../../job-tracker-ui/src/components/EditJobDialog.tsx#L1) | 261 | reachable | JobTable.tsx, ApplicationWorkspacePage.tsx | Autocomplete, Box, Button, Checkbox, Chip, DatePicker, Dialog, DialogActions, DialogContent, DialogTitle, FormControlLabel, MenuItem, Paper, TagsInput, TextField, Typography |
|
||||
| [src/components/EmailProviderConnections.tsx:1](../../../job-tracker-ui/src/components/EmailProviderConnections.tsx#L1) | 247 | reachable | ConnectedAccountsPage.tsx | Box, Button, CheckCircleIcon, Checkbox, Chip, Divider, FormControlLabel, Paper, ProviderRow, Stack, TextField, Typography |
|
||||
| [src/components/ErrorBoundary.tsx:1](../../../job-tracker-ui/src/components/ErrorBoundary.tsx#L1) | 63 | reachable | ClientApp.tsx | ErrorBoundaryInner |
|
||||
| [src/components/GoogleAuthCard.tsx:1](../../../job-tracker-ui/src/components/GoogleAuthCard.tsx#L1) | 301 | reachable | LoginPage.tsx, ProfilePage.tsx | Box, Button, Chip, Paper, TwoFactorChallenge, Typography |
|
||||
| [src/components/GradientButton.tsx:1](../../../job-tracker-ui/src/components/GradientButton.tsx#L1) | 42 | reachable | LandingPage.tsx | Button |
|
||||
| [src/components/ImportExportJobs.tsx:1](../../../job-tracker-ui/src/components/ImportExportJobs.tsx#L1) | 282 | reachable | SettingsView.tsx | Box, Button, Paper, Typography |
|
||||
| [src/components/InterviewPrep.tsx:1](../../../job-tracker-ui/src/components/InterviewPrep.tsx#L1) | 512 | reachable | ApplicationWorkspacePage.tsx | Alert, ApplicationFollowUp, AutoFixHighIcon, Box, Button, Checkbox, Chip, DeleteOutlineIcon, Divider, IconButton, InterviewAiAssistant, LinearProgress, MenuItem, Paper, PrepRow, Shell, Skeleton, Stack, TextField, Tooltip, Typography |
|
||||
| [src/components/JobDetailsPanels.tsx:1](../../../job-tracker-ui/src/components/JobDetailsPanels.tsx#L1) | 59 | reachable | ApplicationWorkflowAssist.tsx | Box, Button, ListCard, TextField, Typography |
|
||||
| [src/components/JobFlowBar.tsx:1](../../../job-tracker-ui/src/components/JobFlowBar.tsx#L1) | 186 | outside graph | — | Box, Chip, CloseIcon, EmojiEventsIcon, ForumIcon, MarkEmailReadIcon, React.Fragment, Typography, WorkOutlineIcon |
|
||||
| [src/components/JobTable.tsx:1](../../../job-tracker-ui/src/components/JobTable.tsx#L1) | 866 | reachable | App.tsx, SettingsView.tsx | Box, Button, Checkbox, Chip, DeleteOutlineIcon, EditJobDialog, EditOutlinedIcon, EmptyJobsState, FormControl, FormControlLabel, IconButton, InputAdornment, InputLabel, Menu, MenuItem, MoreHorizIcon, Paper, RestoreFromTrashOutlinedIcon, SavedViewsMenu, SearchIcon, Select, Stack, Table, TableBody, TableCell, TableHead, TablePagination, TableRow, TableSortLabel, TextField, Tooltip, Typography, ViewColumnIcon, ViewStateNotice, WorkOutlineIcon |
|
||||
| [src/components/KanbanBoard.tsx:1](../../../job-tracker-ui/src/components/KanbanBoard.tsx#L1) | 428 | reachable | App.tsx | Alert, Box, Card, CardContent, Chip, IconButton, ListSubheader, Menu, MenuItem, MoreHorizIcon, Paper, Typography, ViewStateNotice |
|
||||
| [src/components/Markdown.tsx:1](../../../job-tracker-ui/src/components/Markdown.tsx#L1) | 68 | outside graph | — | Box, Link, Typography |
|
||||
| [src/components/MicrosoftAuthCard.tsx:1](../../../job-tracker-ui/src/components/MicrosoftAuthCard.tsx#L1) | 247 | reachable | LoginPage.tsx, MicrosoftLegacyRelinkPage.tsx, ProfilePage.tsx | Box, Button, Chip, Paper, TextField, TwoFactorChallenge, Typography |
|
||||
| [src/components/NotificationsPopover.tsx:1](../../../job-tracker-ui/src/components/NotificationsPopover.tsx#L1) | 168 | reachable | App.tsx | Alert, Box, Button, CircularProgress, CloseIcon, DeleteOutlineIcon, Divider, DoneIcon, IconButton, Popover, Stack, Tooltip, Typography |
|
||||
| [src/components/OnboardingChecklist.tsx:1](../../../job-tracker-ui/src/components/OnboardingChecklist.tsx#L1) | 127 | reachable | DashboardView.tsx | Box, Button, CheckCircleIcon, CloseIcon, IconButton, LinearProgress, Paper, RadioButtonUncheckedIcon, Stack, Typography |
|
||||
| [src/components/ProFeatureNotice.tsx:1](../../../job-tracker-ui/src/components/ProFeatureNotice.tsx#L1) | 55 | reachable | AiSectionAssistant.tsx, CareerProfilePage.tsx, CvBuilderEditor.tsx | Alert, Button, CloseIcon, IconButton, Stack, Typography |
|
||||
| [src/components/QuickCaptureCard.tsx:1](../../../job-tracker-ui/src/components/QuickCaptureCard.tsx#L1) | 70 | reachable | SettingsView.tsx | Box, Paper, TextField, Typography |
|
||||
| [src/components/QuickCommandDialog.tsx:1](../../../job-tracker-ui/src/components/QuickCommandDialog.tsx#L1) | 159 | reachable | App.tsx | Box, Dialog, DialogContent, List, ListItemButton, ListItemText, SearchIcon, TextField, Typography |
|
||||
| [src/components/RemindersView.tsx:1](../../../job-tracker-ui/src/components/RemindersView.tsx#L1) | 139 | reachable | App.tsx | Box, Button, Chip, Divider, Paper, ReminderSection, Typography, ViewStateNotice |
|
||||
| [src/components/RichTextField.tsx:1](../../../job-tracker-ui/src/components/RichTextField.tsx#L1) | 79 | reachable | ApplicationAssets.tsx, CvBuilderEditor.tsx, CareerProfileSections.tsx | Box, FormatBoldIcon, FormatItalicIcon, FormatUnderlinedIcon, IconButton, LinkIcon, TextField, Tooltip |
|
||||
| [src/components/RulesSettingsCard.tsx:1](../../../job-tracker-ui/src/components/RulesSettingsCard.tsx#L1) | 99 | reachable | SettingsView.tsx | Alert, Box, Button, Paper, TextField, Typography |
|
||||
| [src/components/SavedViewsMenu.tsx:1](../../../job-tracker-ui/src/components/SavedViewsMenu.tsx#L1) | 183 | reachable | JobTable.tsx | BookmarkBorderIcon, Button, DeleteOutlineIcon, Divider, IconButton, ListItemText, Menu, MenuItem, TextField, Tooltip |
|
||||
| [src/components/SessionsSettingsCard.tsx:1](../../../job-tracker-ui/src/components/SessionsSettingsCard.tsx#L1) | 148 | reachable | ProfilePage.tsx | Alert, Button, DeleteIcon, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, List, ListItem, ListItemSecondaryAction, ListItemText, Paper, Typography |
|
||||
| [src/components/SettingsView.tsx:1](../../../job-tracker-ui/src/components/SettingsView.tsx#L1) | 244 | reachable | App.tsx | AiPrivacySettingsCard, AiUsageCard, Alert, BackupCard, Box, Button, Checkbox, FormControl, FormControlLabel, ImportExportJobs, InputLabel, MenuItem, Paper, QuickCaptureCard, RulesSettingsCard, SectionCard, Select, Skeleton, Tab, TabPanel, Tabs, Typography |
|
||||
| [src/components/TagsInput.tsx:1](../../../job-tracker-ui/src/components/TagsInput.tsx#L1) | 37 | reachable | AddJobModal.tsx, EditJobDialog.tsx | Autocomplete, Chip, TextField |
|
||||
| [src/components/TurnstileWidget.tsx:1](../../../job-tracker-ui/src/components/TurnstileWidget.tsx#L1) | 37 | reachable | LoginPage.tsx | Box, Typography |
|
||||
| [src/components/TwoFactorChallenge.tsx:1](../../../job-tracker-ui/src/components/TwoFactorChallenge.tsx#L1) | 84 | reachable | GoogleAuthCard.tsx, MicrosoftAuthCard.tsx, LoginPage.tsx | Alert, Box, Button, Checkbox, FormControlLabel, TextField, Typography |
|
||||
| [src/components/TwoFactorSettingsCard.tsx:1](../../../job-tracker-ui/src/components/TwoFactorSettingsCard.tsx#L1) | 391 | reachable | ProfilePage.tsx | Alert, Box, Button, Checkbox, DeleteIcon, Dialog, DialogActions, DialogContent, DialogTitle, Divider, FormControlLabel, IconButton, List, ListItem, ListItemSecondaryAction, ListItemText, Paper, TextField, Typography |
|
||||
| [src/components/UserManagementCard.tsx:1](../../../job-tracker-ui/src/components/UserManagementCard.tsx#L1) | 184 | outside graph | — | Box, Button, Paper, TextField, Typography |
|
||||
| [src/components/ViewStateNotice.tsx:1](../../../job-tracker-ui/src/components/ViewStateNotice.tsx#L1) | 51 | reachable | CompaniesTable.tsx, DashboardView.tsx, JobTable.tsx, KanbanBoard.tsx, RemindersView.tsx, AdminAuditPage.tsx | Alert, Box, Button, CircularProgress, Typography |
|
||||
| [src/components/cv/AiSectionAssistant.tsx:1](../../../job-tracker-ui/src/components/cv/AiSectionAssistant.tsx#L1) | 113 | reachable | CvBuilderEditor.tsx | Alert, AutoFixHighIcon, Box, Button, MenuItem, Paper, ProFeatureNotice, Stack, TextField, Typography |
|
||||
| [src/components/cv/CvCustomizeTab.tsx:1](../../../job-tracker-ui/src/components/cv/CvCustomizeTab.tsx#L1) | 103 | reachable | CvBuilderEditor.tsx | Box, Button, ControlSlider, CvTemplateGallery, Divider, FormControl, FormControlLabel, IconButton, InputLabel, MenuItem, Paper, Select, Slider, Stack, Switch, TextField, Typography |
|
||||
| [src/confirm.tsx:1](../../../job-tracker-ui/src/confirm.tsx#L1) | 88 | reachable | App.tsx, InterviewPrep.tsx, dialogs.ts, ApplicationWorkspacePage.tsx, CorrespondenceInboxPage.tsx, CareerEvidenceBank.tsx | Alert, Button, ConfirmContext.Provider, Dialog, DialogActions, DialogContent, DialogTitle, Typography |
|
||||
| [src/i18n/I18nProvider.tsx:1](../../../job-tracker-ui/src/i18n/I18nProvider.tsx#L1) | 67 | reachable | App.tsx, ClientApp.tsx, AddJobModal.tsx, AiPrivacySettingsCard.tsx, AiUsageCard.tsx, ApplicationAssets.tsx, ApplicationCalendarActions.tsx, ApplicationChecklist.tsx, ApplicationIntelligence.tsx, ApplicationWorkflowAssist.tsx, Attachments.tsx, AuthStatusCard.tsx, BackupCard.tsx, CompaniesTable.tsx, Correspondence.tsx, CropImageDialog.tsx, CvTemplateGallery.tsx, DashboardView.tsx, EditJobDialog.tsx, EmailProviderConnections.tsx, ErrorBoundary.tsx, GoogleAuthCard.tsx, ImportExportJobs.tsx, InterviewPrep.tsx, JobDetailsPanels.tsx, JobTable.tsx, KanbanBoard.tsx, MicrosoftAuthCard.tsx, NotificationsPopover.tsx, OnboardingChecklist.tsx, ProFeatureNotice.tsx, QuickCaptureCard.tsx, QuickCommandDialog.tsx, RemindersView.tsx, RichTextField.tsx, RulesSettingsCard.tsx, SavedViewsMenu.tsx, SessionsSettingsCard.tsx, SettingsView.tsx, TagsInput.tsx, TurnstileWidget.tsx, TwoFactorChallenge.tsx, TwoFactorSettingsCard.tsx, UserManagementCard.tsx, ViewStateNotice.tsx, AiSectionAssistant.tsx, CvCustomizeTab.tsx, confirm.tsx, AppShell.tsx, prompt.tsx, AdminAuditPage.tsx, AdminSystemPage.tsx, AdminUsersPage.tsx, ApplicationWorkspacePage.tsx, CareerProfilePage.tsx, ConnectedAccountsPage.tsx, CorrespondenceInboxPage.tsx, CvBuilderEditor.tsx, CvBuilderPage.tsx, ForgotPasswordPage.tsx, GmailReviewPage.tsx, JobDiscoveryPage.tsx, LandingPage.tsx, LoginPage.tsx, MicrosoftLegacyRelinkPage.tsx, NotFoundPage.tsx, OfferComparisonPage.tsx, OperationsPage.tsx, ProfilePage.tsx, ResetPasswordPage.tsx, RouteErrorPage.tsx, VerifyEmailPage.tsx, CareerEvidenceBank.tsx, CareerProfileSections.tsx, CareerWorkspaceOverview.tsx, ProfileCompleteness.tsx | I18nContext.Provider |
|
||||
| [src/layout/AppShell.tsx:1](../../../job-tracker-ui/src/layout/AppShell.tsx#L1) | 578 | reachable | App.tsx, LandingPage.tsx | AppBar, Avatar, Badge, Box, Breadcrumbs, Button, ButtonGroup, Chip, Divider, Drawer, IconButton, JobbjaktMark, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Menu, MenuIcon, MenuItem, MenuOpenIcon, NotificationsNoneIcon, SettingsOutlinedIcon, StackLanguageToggle, Toolbar, Tooltip, Typography |
|
||||
| [src/prompt.tsx:1](../../../job-tracker-ui/src/prompt.tsx#L1) | 84 | reachable | App.tsx, BackupCard.tsx, dialogs.ts | Button, Dialog, DialogActions, DialogContent, DialogTitle, PromptContext.Provider, TextField, Typography |
|
||||
| [src/toast.tsx:1](../../../job-tracker-ui/src/toast.tsx#L1) | 84 | reachable | App.tsx, AddJobModal.tsx, AiPrivacySettingsCard.tsx, ApplicationWorkflowAssist.tsx, Attachments.tsx, AuthStatusCard.tsx, BackupCard.tsx, CompaniesTable.tsx, Correspondence.tsx, EditJobDialog.tsx, EmailProviderConnections.tsx, GoogleAuthCard.tsx, ImportExportJobs.tsx, JobTable.tsx, MicrosoftAuthCard.tsx, QuickCaptureCard.tsx, RemindersView.tsx, RulesSettingsCard.tsx, SessionsSettingsCard.tsx, SettingsView.tsx, TwoFactorSettingsCard.tsx, UserManagementCard.tsx, AiSectionAssistant.tsx, AdminAuditPage.tsx, AdminUsersPage.tsx, CareerProfilePage.tsx, CorrespondenceInboxPage.tsx, CvBuilderEditor.tsx, CvBuilderPage.tsx, ForgotPasswordPage.tsx, GmailReviewPage.tsx, LoginPage.tsx, ProfilePage.tsx, ResetPasswordPage.tsx | Alert, Button, Snackbar, ToastContext.Provider |
|
||||
| [src/views/AdminAuditPage.tsx:1](../../../job-tracker-ui/src/views/AdminAuditPage.tsx#L1) | 184 | reachable | App.tsx | Box, Button, Chip, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, ViewStateNotice |
|
||||
| [src/views/AdminSystemPage.tsx:1](../../../job-tracker-ui/src/views/AdminSystemPage.tsx#L1) | 676 | reachable | App.tsx | Alert, Box, Button, Checkbox, Chip, DetailRow, FormControlLabel, Paper, Stack, SummaryCard, Tab, Tabs, TextField, Typography |
|
||||
| [src/views/AdminUsersPage.tsx:1](../../../job-tracker-ui/src/views/AdminUsersPage.tsx#L1) | 308 | reachable | App.tsx | Alert, Box, Button, Checkbox, Chip, DataGrid, FormControlLabel, Paper, Stack, TextField, Tooltip, Typography |
|
||||
| [src/views/ApplicationWorkspacePage.tsx:1](../../../job-tracker-ui/src/views/ApplicationWorkspacePage.tsx#L1) | 491 | reachable | App.tsx | Accordion, AccordionDetails, AccordionSummary, Alert, ApplicationAnalysis, ApplicationCalendarActions, ApplicationChecklist, ApplicationCoverLetterSection, ApplicationCvSection, ApplicationInterviewPrep, ApplicationMatch, ApplicationPackageDraftsSection, ApplicationProgress, ApplicationStatusSuggestion, ApplicationStrategySnapshot, ApplicationTimeline, ApplicationWorkspace, ArrowBackIcon, ArrowForwardIcon, Attachments, AutoFixHighIcon, Box, Button, ChecklistIcon, Chip, Correspondence, DescriptionOutlinedIcon, Divider, EditJobDialog, EditOutlinedIcon, ExpandMoreIcon, FolderOutlinedIcon, IconButton, JobDetailsSection, MailOutlineIcon, OpenInNewIcon, OverviewDetails, OverviewSection, Paper, Skeleton, Stack, Tab, Tabs, Tooltip, Typography, WorkspaceHeader |
|
||||
| [src/views/CareerProfilePage.tsx:1](../../../job-tracker-ui/src/views/CareerProfilePage.tsx#L1) | 879 | reachable | CareerWorkspacePage.tsx | Accordion, AccordionDetails, AccordionSummary, Alert, Avatar, Box, Button, CareerEvidenceBank, CareerWorkspaceOverview, Checkbox, Chip, CropImageDialog, DeleteOutlineIcon, EducationSection, ExpandMoreIcon, FormControl, FormControlLabel, InputLabel, InterestsSection, LanguagesSection, LinearProgress, LongTailSections, MenuItem, OtherSectionsSection, Paper, PersonalInformationSection, PhotoCameraOutlinedIcon, ProFeatureNotice, ProfessionalSummarySection, ProfileCompleteness, Select, SkillsSection, Tab, Tabs, TextField, Typography, UploadFileOutlinedIcon, WorkExperienceSection |
|
||||
| [src/views/CareerWorkspacePage.tsx:1](../../../job-tracker-ui/src/views/CareerWorkspacePage.tsx#L1) | 8 | reachable | App.tsx | CareerProfilePage |
|
||||
| [src/views/ConnectedAccountsPage.tsx:1](../../../job-tracker-ui/src/views/ConnectedAccountsPage.tsx#L1) | 26 | reachable | App.tsx | Box, Button, EmailProviderConnections, Paper, Typography |
|
||||
| [src/views/CorrespondenceInboxPage.tsx:1](../../../job-tracker-ui/src/views/CorrespondenceInboxPage.tsx#L1) | 750 | reachable | App.tsx | Alert, Autocomplete, Box, Button, Chip, CircularProgress, FormControl, GmailReviewPage, InputLabel, MailOutlineIcon, MenuItem, Pagination, Paper, Select, Stack, TextField, Typography |
|
||||
| [src/views/CvBuilderEditor.tsx:1](../../../job-tracker-ui/src/views/CvBuilderEditor.tsx#L1) | 1131 | reachable | App.tsx | AddContentCard, AddIcon, AiSectionAssistant, Alert, ArrowBackIcon, ArrowDownwardIcon, ArrowUpwardIcon, AutoFixHighIcon, Box, Button, Chip, Collapse, ContentCopyIcon, ContentTab, CvCustomizeTab, DeleteOutlineIcon, Dialog, DialogActions, DialogContent, DialogTitle, Divider, DocumentAiTab, DragIndicatorIcon, EditorSkeleton, EntryEditor, ExpandMoreIcon, HistoryTab, IconButton, MenuItem, Paper, PictureAsPdfIcon, ProFeatureNotice, PublicIcon, RedoIcon, RichTextField, SaveBadge, SectionRow, Skeleton, SpellcheckIcon, Stack, Tab, Tabs, TextField, Tooltip, TranslateIcon, Typography, UndoIcon, VisibilityIcon, VisibilityOffIcon |
|
||||
| [src/views/CvBuilderPage.tsx:1](../../../job-tracker-ui/src/views/CvBuilderPage.tsx#L1) | 203 | reachable | App.tsx | AddIcon, Alert, Box, Button, Chip, CvTemplateGallery, CvTemplateThumbnail, DescriptionOutlinedIcon, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Menu, MenuItem, MoreVertIcon, Paper, PublicIcon, Stack, TextField, Typography |
|
||||
| [src/views/ForgotPasswordPage.tsx:1](../../../job-tracker-ui/src/views/ForgotPasswordPage.tsx#L1) | 101 | reachable | App.tsx | Alert, Box, Button, Paper, TextField, Typography |
|
||||
| [src/views/GmailReviewPage.tsx:1](../../../job-tracker-ui/src/views/GmailReviewPage.tsx#L1) | 290 | reachable | CorrespondenceInboxPage.tsx | Box, Button, Chip, CircularProgress, Paper, Stack, TextField, Typography |
|
||||
| [src/views/JobDiscoveryPage.tsx:1](../../../job-tracker-ui/src/views/JobDiscoveryPage.tsx#L1) | 220 | reachable | App.tsx | AddIcon, Alert, BookmarkAddOutlinedIcon, Box, Button, Card, CardActions, CardContent, Chip, CircularProgress, DeleteOutlineIcon, FormControlLabel, MenuItem, RefreshIcon, SearchIcon, Stack, Switch, TextField, Typography |
|
||||
| [src/views/LandingPage.tsx:1](../../../job-tracker-ui/src/views/LandingPage.tsx#L1) | 282 | reachable | App.tsx | AlarmIcon, AttachIcon, Box, Button, Container, DashboardIcon, GradientButton, InsightsIcon, MailIcon, MatchIcon, Stack, StackLanguageToggle, Typography |
|
||||
| [src/views/LoginPage.tsx:1](../../../job-tracker-ui/src/views/LoginPage.tsx#L1) | 279 | reachable | App.tsx | Alert, Box, Button, Checkbox, Divider, FormControlLabel, GoogleAuthCard, MicrosoftAuthCard, Paper, TextField, TurnstileWidget, TwoFactorChallenge, Typography |
|
||||
| [src/views/MicrosoftLegacyRelinkPage.tsx:1](../../../job-tracker-ui/src/views/MicrosoftLegacyRelinkPage.tsx#L1) | 67 | reachable | App.tsx | Alert, Box, Button, CircularProgress, Paper, Typography |
|
||||
| [src/views/NotFoundPage.tsx:1](../../../job-tracker-ui/src/views/NotFoundPage.tsx#L1) | 41 | reachable | App.tsx | Box, Button, Paper, Typography |
|
||||
| [src/views/OfferComparisonPage.tsx:1](../../../job-tracker-ui/src/views/OfferComparisonPage.tsx#L1) | 67 | reachable | App.tsx | Alert, Box, Button, Chip, Fact, Paper, Skeleton, Stack, Typography |
|
||||
| [src/views/OperationsPage.tsx:1](../../../job-tracker-ui/src/views/OperationsPage.tsx#L1) | 148 | reachable | App.tsx | Alert, Box, Button, Chip, LinearProgress, Paper, Stack, Typography |
|
||||
| [src/views/ProfilePage.tsx:1](../../../job-tracker-ui/src/views/ProfilePage.tsx#L1) | 373 | reachable | App.tsx | Alert, AuthStatusCard, Avatar, Box, Button, Chip, CropImageDialog, DeleteOutlineIcon, Divider, GoogleAuthCard, MicrosoftAuthCard, Paper, PhotoCameraOutlinedIcon, SessionsSettingsCard, TextField, TwoFactorSettingsCard, Typography |
|
||||
| [src/views/PublicCvPage.tsx:1](../../../job-tracker-ui/src/views/PublicCvPage.tsx#L1) | 87 | reachable | App.tsx | |
|
||||
| [src/views/ResetPasswordPage.tsx:1](../../../job-tracker-ui/src/views/ResetPasswordPage.tsx#L1) | 115 | reachable | App.tsx | Alert, Box, Button, Paper, TextField, Typography |
|
||||
| [src/views/RouteErrorPage.tsx:1](../../../job-tracker-ui/src/views/RouteErrorPage.tsx#L1) | 53 | reachable | App.tsx | Box, Button, Paper, Typography |
|
||||
| [src/views/VerifyEmailPage.tsx:1](../../../job-tracker-ui/src/views/VerifyEmailPage.tsx#L1) | 77 | reachable | App.tsx | Alert, Box, Button, CircularProgress, Paper, Typography |
|
||||
| [src/views/career/CareerEvidenceBank.tsx:1](../../../job-tracker-ui/src/views/career/CareerEvidenceBank.tsx#L1) | 39 | reachable | CareerProfilePage.tsx | Alert, Box, Button, Chip, DeleteOutlineIcon, MenuItem, Paper, Stack, TextField, Typography |
|
||||
| [src/views/career/CareerProfileSections.tsx:1](../../../job-tracker-ui/src/views/career/CareerProfileSections.tsx#L1) | 252 | reachable | CareerProfilePage.tsx | AddIcon, Box, Button, Chip, DeleteOutlineIcon, FieldReviewNote, IconButton, LinesField, RichTextField, Stack, TextField, Typography |
|
||||
| [src/views/career/CareerWorkspaceOverview.tsx:1](../../../job-tracker-ui/src/views/career/CareerWorkspaceOverview.tsx#L1) | 178 | reachable | CareerProfilePage.tsx | ActionCard, Alert, Box, Button, Chip, DescriptionOutlinedIcon, LinearProgress, Paper, PersonOutlineIcon, Skeleton, Stack, Typography, UploadFileOutlinedIcon, WorkOutlineIcon |
|
||||
| [src/views/career/ProfileCompleteness.tsx:1](../../../job-tracker-ui/src/views/career/ProfileCompleteness.tsx#L1) | 91 | reachable | CareerProfilePage.tsx | Accordion, AccordionDetails, AccordionSummary, Box, Button, Chip, ExpandMoreIcon, LinearProgress, Typography |
|
||||
@@ -0,0 +1,98 @@
|
||||
# Protected functionality ledger
|
||||
|
||||
This is the current source-backed preservation baseline. **All rows are Preserve** until a later approved migration explicitly records relocation, merger or deprecation. Target-only ideas are separated at the end. A component's existence proves implemented behavior, not live provider availability or usability quality. The [API census](API_CALL_SITES.md) and [component census](COMPONENT_INVENTORY.md) supply the individual call sites/consumers behind these groups.
|
||||
|
||||
## Entry, navigation and account
|
||||
|
||||
| ID | Current user-facing function | Source / important contract |
|
||||
|---|---|---|
|
||||
| E01 | Public product explanation, Free/Pro feature comparison, honest unavailable-billing states and sign-in/register links | `LandingPage`, `planCatalog`; do not invent prices or purchasable capabilities |
|
||||
| E02 | Local sign-in/registration, remember-me, configured Turnstile, resend verification, reset password, verify email | `LoginPage`, reset/verification views, `TurnstileWidget`; server configuration controls availability |
|
||||
| E03 | Google/Microsoft sign-in/link flows, Microsoft legacy relink, provider popup success/error handling | `GoogleAuthCard`, `MicrosoftAuthCard`, `MicrosoftLegacyRelinkPage`; OAuth/state/origin rules remain |
|
||||
| E04 | 2FA challenge, recovery codes, setup/verify/disable/regenerate, trusted devices and revocation | `TwoFactorChallenge`, `TwoFactorSettingsCard`; preserve sensitive confirmation and recovery presentation |
|
||||
| E05 | Active session list, current-device distinction, single/other-session revocation, logout | `SessionsSettingsCard`, `AppShell`, `auth`, `sessionBoundary`; invalidation must clear private UI |
|
||||
| E06 | Avatar upload/remove, name/display name/headline, account email-change request/cancel/confirm, local password change | `ProfilePage`; account identity is distinct from canonical career data |
|
||||
| E07 | Collapsible desktop sidebar, mobile drawer, active subsection matching, keyboard command launcher | `AppShell`, `QuickCommandDialog`; job/company search and fixed navigation/add commands |
|
||||
| E08 | Theme light/dark/system, EN/Bokmål preference with server hydration, toast/confirm/prompt and error routes | `themePrefs`, `I18nProvider`, `toast`, `confirm`, `prompt`, route error/not-found views |
|
||||
| E09 | Cross-tab account switch, stale mutation/read rejection, BFCache/focus revalidation and reauthentication | `api`, `sessionBoundary`, `App`; B02 server precondition and client unmount/abort must survive extraction |
|
||||
|
||||
## Discover and manage jobs
|
||||
|
||||
| ID | Current user-facing function | Source / important contract |
|
||||
|---|---|---|
|
||||
| J01 | Search NAV listings by role/company/municipality, sorting, source/freshness/deadline/work-arrangement details, external listing links | `JobDiscoveryPage`; provider failures and empty results distinguishable |
|
||||
| J02 | Named saved searches, run/delete, automatic alert preference, new/updated results and dismissal | `JobDiscoveryPage`, saved-search APIs; retain owner scope and alert metadata |
|
||||
| J03 | Add job manually or from URL/pasted listing, reviewed preview, company lookup/create, tags and dates, duplicate warning | `AddJobModal`; preview is not a write; keep B01 outbound boundary and existing review step |
|
||||
| J04 | Capture via browser extension, bookmarklet and share/capture query; optional job attachment and tailored CV draft after create | `QuickCaptureCard`, `captureUrl`, `App`, `browser-extension`; preserve payload/URL contracts |
|
||||
| J05 | Job table search/filter/sort/pagination, visible columns/page size, saved named views, row/card actions | `JobTable`, `SavedViewsMenu`; mobile cards and accessible full-workspace entry already exist |
|
||||
| J06 | Selection/bulk status/delete/restore, soft-delete/trash and restore, edit job/company association | `JobTable`, `EditJobDialog`; preserve partial-error handling and confirmation semantics |
|
||||
| J07 | Kanban grouped status views, drag move, keyboard pickup/drop/cancel, direct status selection, job opening | `KanbanBoard`, `pipeline`; same records as table, not a second job model |
|
||||
| J08 | Company directory, recruiter/contact/source/location and pipeline/contact-date editing; company relationship job history | `CompaniesTable`; company creation is integrated with job/import flows, not assumed standalone CRUD |
|
||||
| J09 | Offer comparison including recorded compensation, decision deadline and notes, source-job links | `OfferComparisonPage`; no new compensation calculator implied |
|
||||
| J10 | JSON/CSV job export; JSON import; CSV-to-import-JSON conversion and import counts | `ImportExportJobs`; preserve B05 blob bytes/BOM, spreadsheet safety and typed formats; do not claim full account restore from job import |
|
||||
|
||||
## Job workspace and application artifacts
|
||||
|
||||
| ID | Current user-facing function | Source / important contract |
|
||||
|---|---|---|
|
||||
| W01 | Dedicated job workspace and reusable quick overlay; overview/analysis/CV/cover-letter/interview sections; old deep-link mapping | `ApplicationWorkspacePage`, `ApplicationWorkspace`, `jobWorkspaceRoute`; retain full-page/overlay parity |
|
||||
| W02 | Job detail/status/progression, next actions, dates, description, recruiter/contact and timeline | `JobDetailsSection`, `ApplicationProgress`, `ApplicationTimeline`; do not redefine pipeline enums or history |
|
||||
| W03 | Analysis, profile match/gaps, strategy snapshot, workflow assistance and status suggestions | `ApplicationAnalysis`, `ApplicationMatch`, `ApplicationStatusSuggestion`, `ApplicationStrategySnapshot`; show provenance/loading/failure and confirmation |
|
||||
| W04 | Checklist create/edit/complete/delete/order, progress and recommended next action | `ApplicationChecklist`; keep keyboard reorder and persisted item identity |
|
||||
| W05 | Select/attach a CV, create/tailor document variants, review tailoring guidance and selected-source context | `ApplicationCvSection`, `ApplicationTailoringSection`, `applicationWorkspace`; owner+job association enforced by API |
|
||||
| W06 | Cover-letter editing, AI suggestion review/reject/apply, saved versions and restore, unsaved navigation protection | `ApplicationAssets`, `CoverLetterAiAssistant`; document override must not mutate master profile |
|
||||
| W07 | Application draft fields, submission/package preparation, frozen submitted-package versions and archived attachment download | `ApplicationAssets`, `SubmittedPackagesSection`, `applicationWorkspace`; historical package is distinct from current draft |
|
||||
| W08 | Attachments upload/drag-drop, category/purpose, rename, AI-use flag, preview/download/delete | `Attachments`; owner-scoped binary retrieval, consent selection and size/error handling |
|
||||
| W09 | Interview questions/categories, manual items, answers, ready status, remove, contextual AI review/add-to-prep | `InterviewPrep`, `applicationWorkspace`; generated facts/answers require review |
|
||||
| W10 | Interview debrief template and follow-up content/date, readiness and next-action state | `InterviewPrep`; neutral prompts must not seed invented company/achievement facts |
|
||||
| W11 | Follow-up/reminder workflow, rule-driven dates/stages, notifications, deadline/follow-up ICS and Google/Outlook calendar event actions | `RemindersView`, `RulesSettingsCard`, `ApplicationCalendarActions`; calendar integration already exists, date-only/timestamp semantics must survive |
|
||||
| W12 | Async operation progress, pending/failed/retry/cancel states and associated notifications | `OperationsPage`, profile processing components; preserve operation IDs and server state, avoid duplicate starts on rerender |
|
||||
|
||||
## Career Profile and CVs
|
||||
|
||||
| ID | Current user-facing function | Source / important contract |
|
||||
|---|---|---|
|
||||
| C01 | Canonical structured career profile: personal details, summary, skills, work, education, languages, interests and long-tail/custom sections | `CareerProfilePage`, `views/career/*`; profile save is an account singleton, CV is an identified derived resource |
|
||||
| C02 | Profile overview, completeness/import guidance, manual edit, copy raw CV text, avatar and version history/restore | `CareerWorkspacePage`, `CareerProfilePage`; preserve projection/history behavior without redesigning schema |
|
||||
| C03 | CV/file upload and extraction, rebuild/improve/reprocess, progress/history, diff, explicit low-confidence selection, accept/discard, retry/cancel | `CareerProfilePage`, `/profile-cv/*`; uploaded proposal is not silently canonical truth |
|
||||
| C04 | Evidence bank: sourced statement/title/category/tags, add/list/delete and truthfulness guidance | `CareerEvidenceBank`; evidence belongs to profile owner and is not AI-invented experience |
|
||||
| C05 | CV library create/name/copy/delete, template gallery and real sample thumbnails, publish/unpublish/share and PDF download | `CvBuilderPage`, `cvBuilder`; separate public slug from numeric private ID |
|
||||
| C06 | Studio Template/Content/Customize/AI Tools/History navigation; debounced preview and save state | `CvBuilderEditor`; existing mobile edit/preview and desktop split must retain parity |
|
||||
| C07 | Built-in item visibility/order, custom sections, preset/free-text section catalog, item/content overrides, hide/remove, keyboard reorder | `CvBuilderEditor`, `components/cv/*`; selected profile source and overrides remain distinguishable |
|
||||
| C08 | Template-capability-aware typography/colors/header/headings, skills presentation/groups, one/two-column and sidebar settings, photo/icons | `CvCustomizeTab`, theme registry; retain unsupported-setting handling and server render equivalence |
|
||||
| C09 | A4/Letter, density, margins/spacing, date format, document language, per-section rows/grid/compact/bubbles and columns | `cvBuilder`, `CvCustomizeTab`, content controls; do not drop advanced controls merely to simplify layout |
|
||||
| C10 | Undo/redo of editor settings, save queue, unsaved guard, history/version restore and preview lifecycle | `CvBuilderEditor`; current queue serializes one mounted editor only, not concurrent browsers |
|
||||
| C11 | Per-section AI improve/translate/custom instruction and whole-document translate/improve/spelling review | `AiSectionAssistant`, builder AI tab; source/target language, current/suggestion comparison, apply/reject |
|
||||
| C12 | Authenticated PDF export and anonymous published-CV preview/PDF; long searchable multipage documents | `PublicCvPage`, `cvBuilder`, server renderer; B03 shared resource admission and public ownership/publication checks |
|
||||
|
||||
## Correspondence and external accounts
|
||||
|
||||
| ID | Current user-facing function | Source / important contract |
|
||||
|---|---|---|
|
||||
| M01 | Job-scoped manual note/email log, search, delete, paste/import message; current job/company context | `Correspondence`; manual record is different from sending a real email |
|
||||
| M02 | Gmail candidate search/import, linked-thread refresh/sync history, import thread, unlink/relink/move with job selection | `Correspondence`; cross-job relationship changes remain owner-bound |
|
||||
| M03 | Global correspondence inbox with pagination/search/filter/direction/provider/link state, full message and attachment information, source-job links | `CorrespondenceInboxPage`; provider read failure distinct from no messages |
|
||||
| M04 | Compose/reply, choose connected provider and job/recipient, save/resume/delete drafts, review/confirm send, delivery states and explicit new attempt | `CorrespondenceInboxPage`; persisted draft revision and send idempotency/uncertain delivery controls must survive navigation changes |
|
||||
| M05 | Gmail review candidates, proposed jobs, link/reject/keep decisions, notes, manual sync and create suggested job | `GmailReviewPage` embedded in inbox; retain legacy review redirect |
|
||||
| M06 | Gmail/Google and Microsoft Graph connection/status/disconnect, IMAP connection/status/disconnect | `EmailProviderConnections`, `ConnectedAccountsPage`; login identity and mail-provider identity are separate capabilities |
|
||||
|
||||
## Dashboard, settings and administration
|
||||
|
||||
| ID | Current user-facing function | Source / important contract |
|
||||
|---|---|---|
|
||||
| S01 | Personal dashboard counts, activity/funnel/company/skill trends, stage/salary insights and actionable next steps | `DashboardView`, analytics APIs; chart transformations and empty/error states preserved |
|
||||
| S02 | Five per-owner local visibility preferences; onboarding progress and dismiss; notification bell/unread/read/dismiss | `DashboardView`, `OnboardingChecklist`, `NotificationsPopover`; no server widget-order/resize contract exists yet |
|
||||
| S03 | Follow-up/ghosting rule settings, email reminder preference, table preferences, theme/language and connected-account links | `SettingsView`, `RulesSettingsCard`; preferences have different scopes, do not replace with one unsafely shared object |
|
||||
| S04 | AI privacy settings, usage/limits, honest Free/Pro lock states, billing status, conditional checkout and portal | `AiPrivacySettingsCard`, `AiUsageCard`, `AccountPlanProvider`; server entitlement authoritative, not client context defaults |
|
||||
| S05 | Account export, encrypted backup download, lifecycle status and deliberate deletion confirmation | `BackupCard`; recent-auth/password/provider restrictions remain; a downloadable backup is not proven restore readiness |
|
||||
| A01 | Admin user list/create, role promotion/demotion guards, reset link and delete with last-admin/self warnings | `AdminUsersPage`, `/users`; API roles enforce privilege regardless of navigation |
|
||||
| A02 | Admin audit event list/detail, supported undo and job restore | `AdminAuditPage`; preserve event/ownership semantics rather than generic mutation buttons |
|
||||
| A03 | Separate system health/build/database/AI/email status, SMTP settings/test, AI probe, CV corpus benchmark and maintenance run controls | `AdminSystemPage`; sensitive config values/logs must not move into personal dashboard |
|
||||
|
||||
## Target brief items that are not current features
|
||||
|
||||
The target grouped navigation would reorganize an existing collapsible sidebar. Jobs/Table and Kanban can become view choices over the existing APIs. Dedicated Analytics/Documents/Notifications destinations would relocate embedded capabilities. They are not permission to delete offers, reminders, correspondence review, operations or legacy URLs.
|
||||
|
||||
Dashboard drag/order/resize/reset and cross-device persistence are new work beyond the five local booleans. A general assistant/chat, goals system, new brand/name and additional email/calendar providers are not implied by existing contextual AI or integrations. Retain implemented Google/Outlook calendar actions even though the product brief describes broader calendar ambitions as future work.
|
||||
|
||||
During migration, extend this table with destination, regression test and review evidence per ID. Do not treat a screen screenshot or a count of passing tests as proof that all rows survived.
|
||||
@@ -0,0 +1,92 @@
|
||||
# Phase 1 — Frontend audit
|
||||
|
||||
Date: 2026-09-09. Source checkpoint: `97fce89c002fe86e737ca7387170321d464b80d7` (application changes through `0954876`; subsequent commits contain the brief and CI prerequisite corrections). Audit branch: `codex/ui-redesign-audit`. Test-only packaging correction `23cc250` leaves the frontend census unchanged; its fresh 22 PDF and 915 broader backend passes are recorded in the test assessment.
|
||||
|
||||
**Phase 1 source audit complete; redesign implementation has not started.** The repository already implements much of the proposed workflow. Retain its MUI/React foundation and domain contracts, improve shared semantics, then migrate representative screens in small steps. A replacement frontend framework or component library is not justified by the observed problems.
|
||||
|
||||
This is a source and regression-evidence audit, not a new visual usability study, production certification, or execution of security ticket B07. The existing security queue still governs unresolved integrity/recovery work. F04 remains open. A pushed revision is not proof of a successful deployment; see [release evidence](../../audits/2026-09-07/validation/b06-completion.md#authorized-release-attempt-and-ci-prerequisite-correction).
|
||||
|
||||
## Deliverables and method
|
||||
|
||||
| Handoff requirement | Evidence |
|
||||
|---|---|
|
||||
| Architecture, styling, state | This document |
|
||||
| Every declared route/page | [Route map](ROUTE_MAP.md): 31 concrete route patterns, including two redirect aliases; 29 page patterns |
|
||||
| Existing user functionality | [Preservation ledger](FUNCTIONALITY_INVENTORY.md), including nested screens and non-navigation entry points |
|
||||
| Components | [All production TSX modules](COMPONENT_INVENTORY.md), shared responsibility map below |
|
||||
| Tests and gaps | [Test assessment](TEST_INVENTORY.md), [test-file census](TEST_FILES.md) |
|
||||
| API integration | [Contract map](API_AND_IDENTITY.md), [266 call expressions](API_CALL_SITES.md) |
|
||||
| Auth, authorization, storage | [Identity and storage boundaries](API_AND_IDENTITY.md) |
|
||||
| Localisation, mobile, accessibility | Assessment below and [regression risks](RISKS_AND_MIGRATION.md) |
|
||||
| Migration and decisions | [Proposed sequence and gates](RISKS_AND_MIGRATION.md) |
|
||||
|
||||
Read the ten documents required by [ASTRA_HANDOFF](../ASTRA_HANDOFF.md), then traced route elements, their local import graph, event handlers, API wrappers, server controllers/services, security middleware, test configuration and existing validation evidence. The [machine-readable census](source-inventory.json) records 120 production TS/TSX files under `src`/`app`, 76 frontend test files, 266 direct shared-client call expressions, and 34 route declarations. Declarations include a duplicated root and two wildcard routing boundaries; they are not 34 pages. File and expression counts are inventory aids, not coverage percentages.
|
||||
|
||||
Regenerate source tables from the repository root after installing the locked frontend dependencies:
|
||||
|
||||
```sh
|
||||
node docs/redesign/audit/generate-inventory.cjs
|
||||
```
|
||||
|
||||
The generator reads tracked source through the installed TypeScript AST. It does not execute application code. API paths supplied through variables are retained as expressions; resolve them with the contract map. CSS, static assets, OAuth SDK traffic and browser-extension entry points require the accompanying manual inspection. Runtime behavior is marked as prior evidence or unverified where this pass did not execute it.
|
||||
|
||||
## Architecture and technology
|
||||
|
||||
The application is a client-rendered React SPA packaged by Next, not a server-rendered Next route application. [Next configuration](../../../job-tracker-ui/next.config.js) exports static production assets and rewrites development deep links to the root. `app/page.tsx` and `app/[[...slug]]/ClientShell.tsx` load `ClientApp` with SSR disabled; `App.tsx` owns React Router. Nginx supplies the production SPA fallback and `/api` proxy. Preserve direct URL entry, refresh, history navigation and static deployment together.
|
||||
|
||||
| Concern | Current implementation | Redesign implication |
|
||||
|---|---|---|
|
||||
| Framework | Next 16, React 19, TypeScript strict; exact installed versions in lockfile | Keep build/output model unless a measured requirement needs a change |
|
||||
| Navigation | React Router 7, outer public routes plus authenticated shell's inner `Routes`, lazy feature imports | Consolidate navigation metadata deliberately; do not accidentally introduce a second active route authority |
|
||||
| UI | MUI 7, MUI X Data Grid/Date Pickers, Emotion, MUI icons; TanStack **Table**, not Query | Shared tokens and component composition can implement the brief without a library migration |
|
||||
| Styling | [theme.ts](../../../job-tracker-ui/src/theme.ts), global CSS, MUI overrides, extensive inline `sx`, page-local styling | Theme exists, but duplicated shell/page color and surface choices weaken consistency |
|
||||
| Typography | Archivo, loaded by app layout; theme typography variants | Preserve fallbacks and loading behavior; font self-hosting is a separate deployment/privacy choice |
|
||||
| Data transport | One Axios instance in [api.ts](../../../job-tracker-ui/src/api.ts), thin typed domain wrappers and direct page calls | Keep the B02 interceptors and blob download behavior when extracting components |
|
||||
| State | Local React state/effects; auth, account plan, theme, i18n, toast, prompt and confirm contexts | No Redux, Zustand or React Query store to replace; introduce a cache only for a demonstrated need |
|
||||
| Async UI | `useViewResource`, resource-specific effects, operation polling, custom refresh events, component-local workspace tab cache | Preserve request sequencing, loading/error/refresh distinction and identity invalidation |
|
||||
| Forms | Controlled MUI fields; many page-local draft states | Retain dirty guards and validation while extracting forms; do not add persistent private drafts implicitly |
|
||||
| Documents | Canonical Career Profile, persisted CV settings/overrides, server HTML/PDF renderer, iframe preview | The editor is a domain application, not merely a form to restyle |
|
||||
| Charts | Dashboard custom SVG/chart presentation | Preserve data meaning and add accessible alternatives where needed; no automatic chart-library replacement |
|
||||
|
||||
Dependencies and scripts: [package.json](../../../job-tracker-ui/package.json). Rendering entry and route wiring: [App.tsx](../../../job-tracker-ui/src/App.tsx). No frontend Next API route/server-action backend was found in the audited entry graph; application APIs live in .NET.
|
||||
|
||||
## Shared component responsibilities
|
||||
|
||||
| Existing foundation | Responsibility to retain / improve |
|
||||
|---|---|
|
||||
| `layout/AppShell` navigation model, `QuickCommandDialog` | Collapse/drawer navigation, active-route matching, capture actions, notifications, command search, logout and identity display |
|
||||
| `theme`, `themePrefs`, `themeBootstrap`, global CSS | Light/dark/system preference, initial paint, semantic colors, spacing and responsive surfaces |
|
||||
| `ViewStateNotice`, `useViewResource`, toast/confirm/prompt | Loaded, empty, failure, retry and confirmation behavior; give them consistent focus and announcement contracts |
|
||||
| `RichTextField`, `TagsInput`, date controls | Plain text/markdown storage and form naming; avoid introducing HTML editing semantics during visual work |
|
||||
| `ApplicationWorkspace`, `ApplicationAssets`, `jobWorkspaceRoute` | Full-page and overlay entry, section/deep-link aliases, derived artifacts and unsaved navigation |
|
||||
| `components/cv/*`, `CvTemplateGallery`, `CvTemplateThumbnail`, `cvBuilder` | Capability-aware design settings, content editing, sample rendering, ordering and public/export contracts |
|
||||
| `AiSectionAssistant`, cover-letter AI, interview AI, `aiWorkspace` | Context selection, entitlement states, current/suggested review, explicit acceptance and provenance |
|
||||
| Account security/settings cards | OAuth links, mail connections, 2FA, sessions, exports, deletion and billing capabilities |
|
||||
|
||||
The complete component table includes four production modules outside the current ClientApp import graph: `Attachment`, `JobFlowBar`, `Markdown`, `UserManagementCard`. These are cleanup candidates only after checking non-app consumers and preservation coverage. App entry modules are naturally outside that graph. **Nothing is approved for deletion in Phase 1.**
|
||||
|
||||
## Localisation
|
||||
|
||||
[I18nProvider](../../../job-tracker-ui/src/i18n/I18nProvider.tsx) uses a typed EN/Bokmål dictionary, string interpolation, English fallback and `uiLanguage` local preference. Default is English unless a stored Norwegian code is present; authenticated `/auth/me` hydration restores the server preference. Changes PUT `/auth/preferences/language`; the document language becomes `en` or `nb-NO`. UI language and CV/AI document language are distinct controls and must remain so.
|
||||
|
||||
Most screen text is translated. There are real consistency gaps, for example the mobile job-card accessible name is hardcoded English at [JobTable:661](../../../job-tracker-ui/src/components/JobTable.tsx#L661). API errors and user-generated content are not automatically translated. Reusing translated labels, date/status formatters and long-string layouts should precede per-page copy changes. Browser accessibility tests currently force English; they do not prove Bokmål fit, pronunciation, errors or document formatting. Existing data and language preferences do not require Connor to decide a new default during this audit.
|
||||
|
||||
## Responsive behavior and accessibility
|
||||
|
||||
The code already adapts several workflows. `AppShell` changes to a drawer below 768 px; desktop sidebar has expanded/collapsed states. `JobTable` uses mobile cards and a separate filter arrangement. Kanban permits narrow-screen horizontal scrolling, keyboard pick-up/drop and a live region. Settings switch from tabs to a labelled select on small screens. The CV editor uses edit/preview panes below 900 px rather than shrinking the desktop split. These are preservation requirements, not missing features.
|
||||
|
||||
Responsiveness remains locally defined through mixed media queries and MUI breakpoints. Drawer/dialog nesting, long job titles, tables, email threads and document preview require a common layout contract plus real mobile testing. No new screenshot study or screen-reader session was performed in this Phase 1 pass.
|
||||
|
||||
The prior [validated accessibility evidence](../../audits/2026-09-07/validation/README.md#accessibility-conclusions) is **F14**, not draft-recovery F09. It measured shared contrast failures and a preview scroll-region focus failure after a viewport transition. Those are not evidence that every custom control is inaccessible. Current builder rich-text call sites supply labels and Kanban has keyboard support. `RichTextField` still permits unnamed usages in its optional props, and some Customize select patterns need an explicit accessible-name check. These are targeted verification points, not newly reproduced violations.
|
||||
|
||||
The automated axe suite samples eight routes and largely waits for `body`/`main`. It can miss loaded content, expanded editors, dialogs and errors. Before migration approval, use populated states, EN/NB, both themes, desktop/mobile; manually test keyboard and NVDA/Narrator, focus restoration, reauthentication, 200%/400% zoom, 320 CSS-pixel reflow, text spacing, forced colors, reduced motion and touch alternatives. Fix shared contrast semantics and the actual preview focus boundary before duplicating new page layouts.
|
||||
|
||||
## Principal conclusions
|
||||
|
||||
1. Preserve the working domain model and security boundaries; new page organization must not redefine ownership, CV persistence, AI acceptance or export formats.
|
||||
2. The full job workspace, canonical Career Profile, contextual AI review, CV history and adaptive mobile surfaces already exist. The redesign should improve coherence and discoverability.
|
||||
3. Shared visual semantics and loaded-state accessibility coverage are weaker than the broad test count suggests. Fix foundations before whole-page migration.
|
||||
4. Five local dashboard visibility switches are not the proposed configurable dashboard. Ordering, resizing and cross-device persistence are future scope requiring a bounded contract.
|
||||
5. The known standalone TypeScript failure reproduces. The source baseline is documented, but release/production and unresolved integrity gates must not be called green by implication.
|
||||
|
||||
Next work is **Phase 2 — Functional baseline**, subject to the gates in [RISKS_AND_MIGRATION](RISKS_AND_MIGRATION.md). No Phase 2 code, B07, or redesign component changes were made here.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Risks and proposed migration approach
|
||||
|
||||
This report proposes the next steps; it does not authorize or implement Phase 2, B07 or a backend overhaul. Original security findings keep their IDs and queue ownership. [Validated implementation queue](../../audits/2026-09-07/validation/implementation-queue.md) remains the source for those fixes.
|
||||
|
||||
## Prioritized regression risks
|
||||
|
||||
| Risk | Source evidence | Smallest appropriate response / gate |
|
||||
|---|---|---|
|
||||
| Lost identity boundary during a new shell/cache/client | `App`, `api`, `sessionBoundary`; B02 server session preconditions | Keep private provider unmount, immutable provenance, abort/late-response checks and real A→B tests. Session headers never become rate-limit owner identity |
|
||||
| Editor redesign hides existing lost-update behavior | CV save payload lacks expected revision; page-local save queue is not cross-editor concurrency | Coordinate existing D01/D02 integrity tickets before changing save/conflict UX. Do not call history/undo optimistic concurrency or add a generic concurrency framework |
|
||||
| Creation replay becomes easier through capture/dialog rerenders | Preview/duplicate warning and subsequent create are separate requests | Preserve current review flow; existing D04 creation-intent ticket is distinct from identity and record revision. No idempotency work in this audit |
|
||||
| Route consolidation loses entry contracts | Two router layers, legacy `/applications/:id`, old section mappings, `?add`, notification/company deep links | Route manifest + redirect tests before moving navigation; keep capture and OAuth callbacks functional |
|
||||
| New styling repeats existing contrast/focus defects | Validated F14 theme pair contrast; builder preview scroll-region transition | A01 semantic foreground/background/state colors, A02 preview structure, A03 loaded/manual verification before broad page work |
|
||||
| Thin initial-state tests create false confidence | Eight-route axe sample; component API mocks; standalone TS2571 | Phase 2 loaded-interaction and type baseline; require feature-ledger evidence per migrated workflow |
|
||||
| CV/profile semantics blur in a unified editor | Canonical profile save versus CV override/settings and published slug | Clearly display source versus document override; test master unchanged, source selection, history, publish/unpublish and long PDF |
|
||||
| AI presentation implies facts or silently applies changes | Contextual suggestions and extraction accept/discard already exist | Preserve preview/reject/apply and source/context metadata; prompt instructions alone do not prove factual accuracy |
|
||||
| Draft/history/mail/package behavior lost in visual simplification | `ApplicationAssets` 769 lines, inbox 750, correspondence 747; separate persistence/attempt APIs | Extract by cohesive responsibility, not one generic form; keep conflict/send uncertainty, frozen package and unsaved guards |
|
||||
| Broad navigation has competing labels/destinations | Eleven main nav entries plus account/admin; profile vs career; table/board separate; embedded operations/review | Design grouped IA with an explicit preservation/redirect map; improve discoverability without deleting capabilities |
|
||||
| Styling consistency remains expensive | Central theme plus hardcoded shell navy/indigo, page-local shadows and large `sx` compositions | Retain MUI; establish tokens and a few layout/field/state primitives, then validate representative surfaces |
|
||||
| Large editor/page modules couple visual and persistence work | Editor 1,131 lines; career 879; job table 866 | One cohesive extraction at a time, bracketed by real workflow tests; file length alone is not a rewrite justification |
|
||||
| Dashboard customization mistaken for an existing server contract | Only five visibility booleans in owner-local storage | Keep current prefs until Phase 8; separately decide device-only vs cross-device contract before persistence/schema work |
|
||||
| International/mobile regressions | Mixed 768/900/MUI breakpoints; hardcoded English mobile accessible name; EN-only axe | Preserve current mobile adaptations; long Bokmål labels and locale/date semantics in the representative matrix |
|
||||
| App route identity churn | Router memo depends on job display preferences in `App` | Potential state-reset risk, not reproduced here; test changing preferences during meaningful workflow before refactoring router ownership |
|
||||
| Unstable release proof or assumed production ingress | New CI prerequisite/build failures; Docker unavailable; F04 open; HTTP redirect observed to unreachable port 444 | No stable/live claim from push alone. Keep required gates and complete operator evidence; no trust-all fallback or invented proxy CIDR |
|
||||
|
||||
Line counts come from the [source census](source-inventory.json); they are prioritization context, not measured performance. No new authorization bypass is alleged by this redesign audit.
|
||||
|
||||
## Recommended order
|
||||
|
||||
1. **Finish the authorized release attempt and retain the checkpoint.** Required CI and deploy preflight must pass before calling the changes live. Production F04 runtime/firewall/DNS/peer checks remain a separate closure gate. Audit/planning can continue without claiming Phase 0 stability.
|
||||
2. **Phase 2 — Functional baseline.** Narrow TS2571 and add full type checking; trace preservation IDs to existing tests; add missing loaded workflow/route/AI-review tests. Preserve B01–B06 regression suites. Coordinate outstanding record-integrity and recovery tickets through their existing queue, without silently starting them here.
|
||||
3. **Phase 3 — UX architecture.** Define grouped navigation, Jobs view switch, destination for embedded Documents/Analytics/Notifications, full-page/preview contract, contextual AI pattern and mobile workflow rules. Map every current route/feature to its destination and backward-compatible entry. Keep API contracts.
|
||||
4. **Phase 4 — Shared foundations.** Use existing MUI/Emotion/theme system. Resolve proven semantic contrast and focus defects, then unify tokens, page/layout/state primitives, labelled fields, buttons, dialogs/drawers and tables. Avoid a speculative new design-system framework.
|
||||
5. **Phase 5 — Representative migration.** Shell → Jobs table/board entry → full job workspace → CV editor; dashboard presentation can join after shell tokens stabilize. Preserve a data-rich populated example, empty/error/locked case, mobile and keyboard path for each. Do not modify editor save semantics concurrently with integrity work.
|
||||
6. **Phase 6 — Review checkpoint.** Inspect EN/NB × light/dark × desktop/mobile, loaded accessibility, long data, CSV/PDF downloads, identity switching and history. Correct shared defects before repeating the design.
|
||||
7. **Phase 7 — Remaining routes and nested functions.** Auth/account, career/import/evidence, CV library/public CV, correspondence, reminders/operations, settings and admin; update every preservation row with evidence.
|
||||
8. **Phase 8 — Dashboard customization.** Add ordering/reset/resizing only with defined layout and persistence semantics. Coordinate any needed migration with restore/rollback readiness. Keep aggregate admin reporting separate.
|
||||
9. **Phase 9 — Cross-product QA and release evidence.** Full regression, manual access/mobile, document pagination and provider/production checks. Feature parity, not only appearance, determines readiness.
|
||||
10. **Phase 10 — Cleanup.** Delete legacy modules only after route/import checks and preservation-ledger completion. Do not use static unreachability alone as approval.
|
||||
|
||||
No router/state/styling dependency replacement is currently recommended. If a later prototype demonstrates a concrete limitation, compare the smallest alternative against MUI reuse and measure migration/keyboard/theme cost before choosing it.
|
||||
|
||||
## Session-sized next scopes and coordination
|
||||
|
||||
| Suggested future scope | Boundaries / expected proof | Parallel constraints |
|
||||
|---|---|---|
|
||||
| Type and baseline bookkeeping | One test payload narrowing, explicit type script/CI gate, known-failure classification | Independent of visual work; coordinate CI edits with deployment repair |
|
||||
| Route/preservation regression | Existing route helpers, full/overlay/capture navigation tests | Do not change router structure at the same time |
|
||||
| Theme semantic contract | Central theme/MUI states + representative loaded contrast fixtures | Separate from backend; integrate before page styling |
|
||||
| Builder focus contract | Actual preview container, viewport transition and keyboard scroll tests | Must not run concurrently with D01/editor save refactor |
|
||||
| Shell/navigation proposal | Documentation/interactive prototype and route map only until Phase 3 approved | Can be prepared while tests run; no new production routing yet |
|
||||
| First screen migration | One agreed shell or Jobs surface with existing handlers/contracts retained | Use settled tokens; no simultaneous edits of its route/state owner |
|
||||
|
||||
These are future implementation boundaries, not work started by Phase 1. Mail delivery, billing, schema, restore and infrastructure changes remain outside redesign sessions unless explicitly authorized and independently gated.
|
||||
|
||||
## Decisions required from Connor
|
||||
|
||||
No answer is required to complete this audit. Ask only when the dependent phase starts:
|
||||
|
||||
- **Brand/name/accent:** the brief intentionally leaves them unsettled. Keep current naming and theme until Phase 3/4 chooses them; do not block baseline tests on branding.
|
||||
- **Dashboard persistence:** whether layout should follow the account across devices materially changes Phase 8's persistence scope. Existing implementation is device-local and owner-keyed.
|
||||
- **Private local draft recovery:** preserve in-memory drafts and existing server drafts now. New persistent device-local career/CV content needs the privacy/retention choice already recorded under W05.
|
||||
- **Product additions/deprecations:** new goals/general assistant/providers or removing an existing preservation row need explicit product scope. Navigation relocation alone need not become a series of permission questions.
|
||||
|
||||
The repository already answers the current framework, default language, existing calendar support, account/profile distinction and owned-resource semantics. Do not ask Connor to supply those facts.
|
||||
|
||||
## Stop conditions
|
||||
|
||||
- No large visual migration until loaded regression baseline and shared UI contracts are defined. No stable release label while required CI is red or deployment state unknown.
|
||||
- No editor persistence redesign before resolving its record conflict contract; B02 must remain green throughout. No schema change before recovery/rollback prerequisites.
|
||||
- No implicit feature deletion, master-profile mutation from CV overrides, silent AI application, unknown email resend, or private cache reuse across identities.
|
||||
- No public accessibility claim without manual primary-flow evidence. No F04 closure without actual deployed/runtime evidence; direct-port failure from one workstation is insufficient.
|
||||
- Stop at Phase 1's audit deliverables in this session. Phase 2 and B07 have not begun.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Current route and page map
|
||||
|
||||
Source: [App.tsx shell routes](../../../job-tracker-ui/src/App.tsx#L379) and [outer router](../../../job-tracker-ui/src/App.tsx#L472). All paths below are current behavior, not target architecture. Preserve or redirect every path intentionally. `:id` and `:slug` represent route patterns, not single records.
|
||||
|
||||
## Public entry routes
|
||||
|
||||
| Route | Component | Contract |
|
||||
|---|---|---|
|
||||
| `/` | LandingPage | Public product/plans and sign-in entry; authenticated redirection behavior has its own test |
|
||||
| `/login` | LoginPage | Local/Google/Microsoft sign-in, verification/2FA branches |
|
||||
| `/register` | LoginPage (`initialMode=register`) | Configuration-gated account creation |
|
||||
| `/forgot-password` | ForgotPasswordPage | Request reset without disclosing account existence |
|
||||
| `/reset-password` | ResetPasswordPage | Token-bearing reset flow |
|
||||
| `/verify-email` | VerifyEmailPage | Verification-token flow |
|
||||
| `/confirm-email-change` | VerifyEmailPage (`emailChange`) | Pending email-change confirmation |
|
||||
| `/microsoft-legacy-relink` | MicrosoftLegacyRelinkPage | Existing-account recovery/relink flow |
|
||||
| `/cv/:slug` | PublicCvPage | Explicitly published CV preview/PDF; no general private CV access |
|
||||
|
||||
## Application routes
|
||||
|
||||
The shell resolves auth/config and `/auth/me`; deployed server authentication remains authoritative. Admin navigation is hidden for ordinary accounts, while API role checks enforce access even for crafted deep links. A routed component is not itself an authorization boundary.
|
||||
|
||||
| Route | Component | Entry / preservation requirement |
|
||||
|---|---|---|
|
||||
| `/dashboard` | DashboardView | Personal metrics, next actions, onboarding and local widget visibility |
|
||||
| `/discover` | JobDiscoveryPage | NAV search, saved searches/alerts, review before tracker import |
|
||||
| `/jobs` | JobTable (`jobs`) | Filters, search, sort, pagination, saved views, columns, selection/bulk actions, full/preview workspace |
|
||||
| `/jobs/:id` | ApplicationWorkspacePage | Full job workspace; section/follow-mode query semantics |
|
||||
| `/reminders` | RemindersView | Follow-ups, deadlines and progression actions |
|
||||
| `/operations` | OperationsPage | Background progress/retry/cancel and notifications; reachable outside main nav |
|
||||
| `/kanban` | KanbanBoard | Alternate view of the same jobs; grouped statuses, keyboard and pointer moves |
|
||||
| `/companies` | CompaniesTable | Company/contact editing and relationship detail; `?edit=id` command entry |
|
||||
| `/offers` | OfferComparisonPage | Comparison of recorded offers and links to source workspaces |
|
||||
| `/correspondence` | CorrespondenceInboxPage | Inbox, provider messages, drafts, reply/send and review mode |
|
||||
| `/correspondence/review` | Redirect | Existing alias to `/correspondence?view=review` |
|
||||
| `/profile` | ProfilePage | Account identity/avatar/password/email; security cards and account links |
|
||||
| `/applications/:id` | LegacyApplicationRedirect | Existing alias to `/jobs/:id`; preserves search and router state |
|
||||
| `/career` | CareerWorkspacePage → CareerProfilePage | Canonical profile, import/review, history and evidence bank |
|
||||
| `/career/builder` | CvBuilderPage | CV library, templates, creation/copy/manage/share/export |
|
||||
| `/career/builder/:id` | CvBuilderEditor | Persisted CV variant studio, preview, history and AI review |
|
||||
| `/admin/audit` | AdminAuditPage | Admin event history and permitted undo/restore |
|
||||
| `/admin/users` | AdminUsersPage | Admin account/role/reset/deletion controls |
|
||||
| `/admin/system` | AdminSystemPage | Admin service/configuration/maintenance/benchmark diagnostics |
|
||||
| `/trash` | JobTable (`trash`) | Deleted-job listing and restoration; retain distinct mode semantics |
|
||||
| `/settings` | SettingsView | General, follow-up rules, notifications and backup/account lifecycle tabs |
|
||||
| `/settings/connected-accounts` | ConnectedAccountsPage | Gmail, Microsoft Graph and IMAP provider connections |
|
||||
|
||||
There are **31 concrete patterns: 29 page patterns and two redirect aliases**. The remaining three declarations in the AST census are the outer `/*` shell, inner `*` NotFoundPage and inner root redirect. The explicit outer `/` landing route takes precedence over the shell's root redirect. RouteErrorPage is an error boundary, not a separate URL. Do not manufacture an `/analytics`, `/documents` or `/notifications` page from the target brief: their current functions are embedded in dashboard/job/operations/settings surfaces.
|
||||
|
||||
## Non-route entries and state contracts
|
||||
|
||||
| Entry | Current effect |
|
||||
|---|---|
|
||||
| Shell add button; command action; capture URL `?add=` / `?addtext=` | Opens AddJobModal and consumes the query. Browser extension/bookmarklet/share entry depends on this |
|
||||
| Job row/card; preview action | Full job page or reused ApplicationWorkspace overlay; preserve close/focus, dirty protection and full-page handoff |
|
||||
| `/jobs/:id?section=...` | Overview, analysis, CV, cover-letter or interview; older `match`, job-details/checklist/documents/timeline/communication values map through existing route helpers |
|
||||
| `/applications/:id` and older tab contracts | Legacy redirects and numeric tab-to-section mapping; covered by route-contract tests |
|
||||
| Command search `Ctrl/Cmd+K` | Jobs and companies plus six static commands; company result uses `/companies?edit=id` |
|
||||
| Notifications/reminders/operations | Deep links can enter a job subsection or processing result without first visiting Jobs |
|
||||
| Builder public/share/PDF | Public slug lifecycle is separate from authenticated numeric CV identity |
|
||||
| OAuth popups/callbacks | Provider/backend callback and postMessage flow; not additional React pages. Preserve exact origin/state contracts |
|
||||
|
||||
Sources: [jobWorkspaceRoute](../../../job-tracker-ui/src/jobWorkspaceRoute.ts), [AppShell](../../../job-tracker-ui/src/layout/AppShell.tsx), [QuickCommandDialog](../../../job-tracker-ui/src/components/QuickCommandDialog.tsx), [workspace component](../../../job-tracker-ui/src/views/ApplicationWorkspacePage.tsx). Phase 3 may propose navigation merges; this inventory does not authorize deleting aliases or current functionality.
|
||||
@@ -0,0 +1,194 @@
|
||||
# Test file inventory
|
||||
|
||||
Tracked test files at the audit baseline. Presence is not proof that a feature or every interaction is covered. See TEST_INVENTORY.md for scope and execution evidence.
|
||||
|
||||
| Layer | File |
|
||||
|---|---|
|
||||
| Backend | [JobTrackerApi.Tests/AccountDataExportTests.cs:1](../../../JobTrackerApi.Tests/AccountDataExportTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AccountDeletionTests.cs:1](../../../JobTrackerApi.Tests/AccountDeletionTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AccountPlansTests.cs:1](../../../JobTrackerApi.Tests/AccountPlansTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AiEvaluationFixtureTests.cs:1](../../../JobTrackerApi.Tests/AiEvaluationFixtureTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AiOperationQueueTests.cs:1](../../../JobTrackerApi.Tests/AiOperationQueueTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AiPrivacyPolicyTests.cs:1](../../../JobTrackerApi.Tests/AiPrivacyPolicyTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AiUsageMeterTests.cs:1](../../../JobTrackerApi.Tests/AiUsageMeterTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AiWorkspaceNotePersistenceTests.cs:1](../../../JobTrackerApi.Tests/AiWorkspaceNotePersistenceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AiWorkspaceTests.cs:1](../../../JobTrackerApi.Tests/AiWorkspaceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AnalyticsSalaryTests.cs:1](../../../JobTrackerApi.Tests/AnalyticsSalaryTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ApiAuthorizationPostureTests.cs:1](../../../JobTrackerApi.Tests/ApiAuthorizationPostureTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ApplicationAssetsTests.cs:1](../../../JobTrackerApi.Tests/ApplicationAssetsTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ApplicationCalendarControllerTests.cs:1](../../../JobTrackerApi.Tests/ApplicationCalendarControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ApplicationChecklistTests.cs:1](../../../JobTrackerApi.Tests/ApplicationChecklistTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ApplicationIntelligenceTests.cs:1](../../../JobTrackerApi.Tests/ApplicationIntelligenceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ApplicationWorkspaceTests.cs:1](../../../JobTrackerApi.Tests/ApplicationWorkspaceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AttachmentConsistencyTests.cs:1](../../../JobTrackerApi.Tests/AttachmentConsistencyTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AttachmentFlagsRecomputeTests.cs:1](../../../JobTrackerApi.Tests/AttachmentFlagsRecomputeTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AttachmentsControllerTests.cs:1](../../../JobTrackerApi.Tests/AttachmentsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AuthAndSystemControllerTests.cs:1](../../../JobTrackerApi.Tests/AuthAndSystemControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AuthSessionRevocationTests.cs:1](../../../JobTrackerApi.Tests/AuthSessionRevocationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/AvatarStorageTests.cs:1](../../../JobTrackerApi.Tests/AvatarStorageTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/BackgroundWorkerTenantTests.cs:1](../../../JobTrackerApi.Tests/BackgroundWorkerTenantTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/BackupControllerTests.cs:1](../../../JobTrackerApi.Tests/BackupControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/BillingControllerTests.cs:1](../../../JobTrackerApi.Tests/BillingControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/BuildMetadataTests.cs:1](../../../JobTrackerApi.Tests/BuildMetadataTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CareerEvidenceControllerTests.cs:1](../../../JobTrackerApi.Tests/CareerEvidenceControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CareerProfileControllerTests.cs:1](../../../JobTrackerApi.Tests/CareerProfileControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CareerProfileServiceTests.cs:1](../../../JobTrackerApi.Tests/CareerProfileServiceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ClientErrorsControllerTests.cs:1](../../../JobTrackerApi.Tests/ClientErrorsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CompanyRelationshipTests.cs:1](../../../JobTrackerApi.Tests/CompanyRelationshipTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CorrespondenceControllerTests.cs:1](../../../JobTrackerApi.Tests/CorrespondenceControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CsvExportTests.cs:1](../../../JobTrackerApi.Tests/CsvExportTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CurrentUserIdLiveEvaluationTests.cs:1](../../../JobTrackerApi.Tests/CurrentUserIdLiveEvaluationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CvBuilderTests.cs:1](../../../JobTrackerApi.Tests/CvBuilderTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CvCorpusHarnessTests.cs:1](../../../JobTrackerApi.Tests/CvCorpusHarnessTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CvExportRetentionTests.cs:1](../../../JobTrackerApi.Tests/CvExportRetentionTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CvExtractionCoverageTests.cs:1](../../../JobTrackerApi.Tests/CvExtractionCoverageTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CvProcessingOperationTests.cs:1](../../../JobTrackerApi.Tests/CvProcessingOperationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/CvProfileDiffServiceTests.cs:1](../../../JobTrackerApi.Tests/CvProfileDiffServiceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/DatabaseBackupRunnerTests.cs:1](../../../JobTrackerApi.Tests/DatabaseBackupRunnerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailControllerTests.cs:1](../../../JobTrackerApi.Tests/EmailControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailDraftPersistenceTests.cs:1](../../../JobTrackerApi.Tests/EmailDraftPersistenceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailDraftsControllerTests.cs:1](../../../JobTrackerApi.Tests/EmailDraftsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailOwnershipIntegrationTests.cs:1](../../../JobTrackerApi.Tests/EmailOwnershipIntegrationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailProviderDeliveryTests.cs:1](../../../JobTrackerApi.Tests/EmailProviderDeliveryTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailSendAttemptStoreTests.cs:1](../../../JobTrackerApi.Tests/EmailSendAttemptStoreTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailSendControllerTests.cs:1](../../../JobTrackerApi.Tests/EmailSendControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/EmailStatusClassifierTests.cs:1](../../../JobTrackerApi.Tests/EmailStatusClassifierTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ExternalOriginTests.cs:1](../../../JobTrackerApi.Tests/ExternalOriginTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ForwardedIngressTests.cs:1](../../../JobTrackerApi.Tests/ForwardedIngressTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/GmailControllerTests.cs:1](../../../JobTrackerApi.Tests/GmailControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/GoogleTokenValidatorTests.cs:1](../../../JobTrackerApi.Tests/GoogleTokenValidatorTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/HumanLanguageCatalogTests.cs:1](../../../JobTrackerApi.Tests/HumanLanguageCatalogTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ImapControllerTests.cs:1](../../../JobTrackerApi.Tests/ImapControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ImapProviderTests.cs:1](../../../JobTrackerApi.Tests/ImapProviderTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ImapServiceSsrfGuardTests.cs:1](../../../JobTrackerApi.Tests/ImapServiceSsrfGuardTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/InterviewAiContextTests.cs:1](../../../JobTrackerApi.Tests/InterviewAiContextTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/InterviewPrepPersistenceTests.cs:1](../../../JobTrackerApi.Tests/InterviewPrepPersistenceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/InterviewPrepTests.cs:1](../../../JobTrackerApi.Tests/InterviewPrepTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsAppliedDateHistoryTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsAppliedDateHistoryTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsAuthorizationTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsAuthorizationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsControllerTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsMariaDraftTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsMariaDraftTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs:1](../../../JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobCvMatchServiceTests.cs:1](../../../JobTrackerApi.Tests/JobCvMatchServiceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobDiscoveryControllerTests.cs:1](../../../JobTrackerApi.Tests/JobDiscoveryControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobImportHttpTransportTests.cs:1](../../../JobTrackerApi.Tests/JobImportHttpTransportTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobImportServiceTests.cs:1](../../../JobTrackerApi.Tests/JobImportServiceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobLifecycleEventTests.cs:1](../../../JobTrackerApi.Tests/JobLifecycleEventTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobOpportunitySyncTests.cs:1](../../../JobTrackerApi.Tests/JobOpportunitySyncTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/JobPipelineTests.cs:1](../../../JobTrackerApi.Tests/JobPipelineTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/LocalAuthIdentityTests.cs:1](../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/MaintenanceJobDispatcherTests.cs:1](../../../JobTrackerApi.Tests/MaintenanceJobDispatcherTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/MeteredSummarizerServiceTests.cs:1](../../../JobTrackerApi.Tests/MeteredSummarizerServiceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/MicrosoftGraphControllerTests.cs:1](../../../JobTrackerApi.Tests/MicrosoftGraphControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/MicrosoftGraphProviderTests.cs:1](../../../JobTrackerApi.Tests/MicrosoftGraphProviderTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/MicrosoftTokenValidatorTests.cs:1](../../../JobTrackerApi.Tests/MicrosoftTokenValidatorTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/MigrationChainTests.cs:1](../../../JobTrackerApi.Tests/MigrationChainTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/NotificationSettingsControllerTests.cs:1](../../../JobTrackerApi.Tests/NotificationSettingsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/OperationsControllerTests.cs:1](../../../JobTrackerApi.Tests/OperationsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/OwnershipGuardTests.cs:1](../../../JobTrackerApi.Tests/OwnershipGuardTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/PdfRenderAdmissionTests.cs:1](../../../JobTrackerApi.Tests/PdfRenderAdmissionTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ProEntitlementAuthorizationTests.cs:1](../../../JobTrackerApi.Tests/ProEntitlementAuthorizationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ProductionConfigTests.cs:1](../../../JobTrackerApi.Tests/ProductionConfigTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/ProfileCvControllerTests.cs:1](../../../JobTrackerApi.Tests/ProfileCvControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/PublicCvControllerTests.cs:1](../../../JobTrackerApi.Tests/PublicCvControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/RateLimitPartitionKeysTests.cs:1](../../../JobTrackerApi.Tests/RateLimitPartitionKeysTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/RouteUniquenessTests.cs:1](../../../JobTrackerApi.Tests/RouteUniquenessTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/RulesEngineProspectTests.cs:1](../../../JobTrackerApi.Tests/RulesEngineProspectTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SavedJobSearchAlertTests.cs:1](../../../JobTrackerApi.Tests/SavedJobSearchAlertTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SessionContextMiddlewareTests.cs:1](../../../JobTrackerApi.Tests/SessionContextMiddlewareTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SessionsControllerTests.cs:1](../../../JobTrackerApi.Tests/SessionsControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SqliteDateTimeOffsetCompatibilityTests.cs:1](../../../JobTrackerApi.Tests/SqliteDateTimeOffsetCompatibilityTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SqliteMigrationHelperTests.cs:1](../../../JobTrackerApi.Tests/SqliteMigrationHelperTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/StageAnalyticsTests.cs:1](../../../JobTrackerApi.Tests/StageAnalyticsTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/StartupSchemaOwnershipTests.cs:1](../../../JobTrackerApi.Tests/StartupSchemaOwnershipTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/StrategySnapshotOperationTests.cs:1](../../../JobTrackerApi.Tests/StrategySnapshotOperationTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SubmittedApplicationPackageTests.cs:1](../../../JobTrackerApi.Tests/SubmittedApplicationPackageTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/SummarizerServiceTests.cs:1](../../../JobTrackerApi.Tests/SummarizerServiceTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/TwoFactorControllerTests.cs:1](../../../JobTrackerApi.Tests/TwoFactorControllerTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/UserOperationStoreTests.cs:1](../../../JobTrackerApi.Tests/UserOperationStoreTests.cs#L1) |
|
||||
| Backend | [JobTrackerApi.Tests/UsersControllerTests.cs:1](../../../JobTrackerApi.Tests/UsersControllerTests.cs#L1) |
|
||||
| Browser extension | [browser-extension/tests/capture-url.test.mjs:1](../../../browser-extension/tests/capture-url.test.mjs#L1) |
|
||||
| Browser / HTTP | [e2e/accessibility.spec.ts:1](../../../job-tracker-ui/e2e/accessibility.spec.ts#L1) |
|
||||
| Browser / HTTP | [e2e/account-isolation.spec.ts:1](../../../job-tracker-ui/e2e/account-isolation.spec.ts#L1) |
|
||||
| Browser / HTTP | [e2e/csv-export.spec.ts:1](../../../job-tracker-ui/e2e/csv-export.spec.ts#L1) |
|
||||
| Browser / HTTP | [e2e/job-discovery.spec.ts:1](../../../job-tracker-ui/e2e/job-discovery.spec.ts#L1) |
|
||||
| Browser / HTTP | [e2e/kanban-theme.spec.ts:1](../../../job-tracker-ui/e2e/kanban-theme.spec.ts#L1) |
|
||||
| Browser / HTTP | [e2e/smoke.spec.ts:1](../../../job-tracker-ui/e2e/smoke.spec.ts#L1) |
|
||||
| Browser / HTTP | [ingress-tests/production.spec.ts:1](../../../job-tracker-ui/ingress-tests/production.spec.ts#L1) |
|
||||
| Browser / HTTP | [pdf-tests/admission.spec.ts:1](../../../job-tracker-ui/pdf-tests/admission.spec.ts#L1) |
|
||||
| Browser / HTTP | [rate-limit-tests/isolation.spec.ts:1](../../../job-tracker-ui/rate-limit-tests/isolation.spec.ts#L1) |
|
||||
| Frontend unit/component | [src/App.test.tsx:1](../../../job-tracker-ui/src/App.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/LandingPage.authRedirect.test.tsx:1](../../../job-tracker-ui/src/LandingPage.authRedirect.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/account-data-export.test.tsx:1](../../../job-tracker-ui/src/account-data-export.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/account-scoped-state.test.tsx:1](../../../job-tracker-ui/src/account-scoped-state.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/admin-audit-page.test.tsx:1](../../../job-tracker-ui/src/admin-audit-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/admin-system-page.test.tsx:1](../../../job-tracker-ui/src/admin-system-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/admin-users-page.test.tsx:1](../../../job-tracker-ui/src/admin-users-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/ai-section-assistant.test.tsx:1](../../../job-tracker-ui/src/ai-section-assistant.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/ai-usage-card.test.tsx:1](../../../job-tracker-ui/src/ai-usage-card.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/app-shell-notifications.test.tsx:1](../../../job-tracker-ui/src/app-shell-notifications.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/application-assets.test.tsx:1](../../../job-tracker-ui/src/application-assets.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/application-calendar.test.tsx:1](../../../job-tracker-ui/src/application-calendar.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/application-checklist.test.tsx:1](../../../job-tracker-ui/src/application-checklist.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/application-drafts.test.ts:1](../../../job-tracker-ui/src/application-drafts.test.ts#L1) |
|
||||
| Frontend unit/component | [src/application-intelligence.test.tsx:1](../../../job-tracker-ui/src/application-intelligence.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/application-route-contracts.test.ts:1](../../../job-tracker-ui/src/application-route-contracts.test.ts#L1) |
|
||||
| Frontend unit/component | [src/application-workflow-assist.test.tsx:1](../../../job-tracker-ui/src/application-workflow-assist.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/application-workspace-overlay.test.tsx:1](../../../job-tracker-ui/src/application-workspace-overlay.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/applicationWorkspace.test.ts:1](../../../job-tracker-ui/src/applicationWorkspace.test.ts#L1) |
|
||||
| Frontend unit/component | [src/attachments.test.tsx:1](../../../job-tracker-ui/src/attachments.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/captureUrl.test.ts:1](../../../job-tracker-ui/src/captureUrl.test.ts#L1) |
|
||||
| Frontend unit/component | [src/career-evidence.test.tsx:1](../../../job-tracker-ui/src/career-evidence.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/career-workspace-page.test.tsx:1](../../../job-tracker-ui/src/career-workspace-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/companies-relationship.test.tsx:1](../../../job-tracker-ui/src/companies-relationship.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/confirm-flow.test.tsx:1](../../../job-tracker-ui/src/confirm-flow.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/confirm.test.tsx:1](../../../job-tracker-ui/src/confirm.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/correspondence-gmail-import.test.tsx:1](../../../job-tracker-ui/src/correspondence-gmail-import.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/correspondence-inbox-page.test.tsx:1](../../../job-tracker-ui/src/correspondence-inbox-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/correspondence-search-context.test.ts:1](../../../job-tracker-ui/src/correspondence-search-context.test.ts#L1) |
|
||||
| Frontend unit/component | [src/csv-export.test.tsx:1](../../../job-tracker-ui/src/csv-export.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/cv-builder-deep-link.test.tsx:1](../../../job-tracker-ui/src/cv-builder-deep-link.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/cv-builder-page.test.tsx:1](../../../job-tracker-ui/src/cv-builder-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/cv-template-thumbnail.test.tsx:1](../../../job-tracker-ui/src/cv-template-thumbnail.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/cvBuilder.test.ts:1](../../../job-tracker-ui/src/cvBuilder.test.ts#L1) |
|
||||
| Frontend unit/component | [src/daily-control-loop.test.tsx:1](../../../job-tracker-ui/src/daily-control-loop.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/dialog-flow.test.tsx:1](../../../job-tracker-ui/src/dialog-flow.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/email-provider-connections.test.tsx:1](../../../job-tracker-ui/src/email-provider-connections.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/end-to-end-trust-loop.test.tsx:1](../../../job-tracker-ui/src/end-to-end-trust-loop.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/gmail-review-page.test.tsx:1](../../../job-tracker-ui/src/gmail-review-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/i18n-provider.test.tsx:1](../../../job-tracker-ui/src/i18n-provider.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/interview-prep.test.tsx:1](../../../job-tracker-ui/src/interview-prep.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/job-discovery.test.tsx:1](../../../job-tracker-ui/src/job-discovery.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/kanban-grouped-board.test.tsx:1](../../../job-tracker-ui/src/kanban-grouped-board.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/landing-page.test.tsx:1](../../../job-tracker-ui/src/landing-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/login-page.test.tsx:1](../../../job-tracker-ui/src/login-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/microsoft-legacy-relink-page.test.tsx:1](../../../job-tracker-ui/src/microsoft-legacy-relink-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/nginx-config.test.ts:1](../../../job-tracker-ui/src/nginx-config.test.ts#L1) |
|
||||
| Frontend unit/component | [src/notifications-popover.test.tsx:1](../../../job-tracker-ui/src/notifications-popover.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/offer-comparison.test.tsx:1](../../../job-tracker-ui/src/offer-comparison.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/onboarding-checklist.test.tsx:1](../../../job-tracker-ui/src/onboarding-checklist.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/operations-page.test.tsx:1](../../../job-tracker-ui/src/operations-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/pipeline.test.ts:1](../../../job-tracker-ui/src/pipeline.test.ts#L1) |
|
||||
| Frontend unit/component | [src/planCatalog.test.ts:1](../../../job-tracker-ui/src/planCatalog.test.ts#L1) |
|
||||
| Frontend unit/component | [src/pro-feature-notice.test.tsx:1](../../../job-tracker-ui/src/pro-feature-notice.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/profile-page.test.tsx:1](../../../job-tracker-ui/src/profile-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/prompt.test.tsx:1](../../../job-tracker-ui/src/prompt.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/public-cv-page.test.tsx:1](../../../job-tracker-ui/src/public-cv-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/quick-capture.test.tsx:1](../../../job-tracker-ui/src/quick-capture.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/session-boundary.test.ts:1](../../../job-tracker-ui/src/session-boundary.test.ts#L1) |
|
||||
| Frontend unit/component | [src/settings-view.test.tsx:1](../../../job-tracker-ui/src/settings-view.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/sidebar-active-nav.test.ts:1](../../../job-tracker-ui/src/sidebar-active-nav.test.ts#L1) |
|
||||
| Frontend unit/component | [src/theme-state.test.tsx:1](../../../job-tracker-ui/src/theme-state.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/turnstile-widget.test.tsx:1](../../../job-tracker-ui/src/turnstile-widget.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/two-factor-settings.test.tsx:1](../../../job-tracker-ui/src/two-factor-settings.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/use-view-resource.test.tsx:1](../../../job-tracker-ui/src/use-view-resource.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/verify-email-page.test.tsx:1](../../../job-tracker-ui/src/verify-email-page.test.tsx#L1) |
|
||||
| Frontend unit/component | [src/workflow-trust-signals.test.tsx:1](../../../job-tracker-ui/src/workflow-trust-signals.test.tsx#L1) |
|
||||
| Repository safety | [scripts/test-ingress-topology.py:1](../../../scripts/test-ingress-topology.py#L1) |
|
||||
| Repository safety | [scripts/test-ingress.py:1](../../../scripts/test-ingress.py#L1) |
|
||||
| Repository safety | [scripts/test-ollama-evaluation.py:1](../../../scripts/test-ollama-evaluation.py#L1) |
|
||||
| Repository safety | [scripts/test-supply-chain.py:1](../../../scripts/test-supply-chain.py#L1) |
|
||||
| Parser / AI service | [tools/summarizer/tests/test_app.py:1](../../../tools/summarizer/tests/test_app.py#L1) |
|
||||
@@ -0,0 +1,58 @@
|
||||
# Test baseline and gaps
|
||||
|
||||
The [test-file census](TEST_FILES.md) lists every discovered tracked frontend test file (76: 67 unit/component and nine browser/HTTP specification files), 106 backend test-source files, plus extension/parser/repository safety files. Counts describe files, not executed cases or coverage percentages. The source snapshot is `97fce89`; subsequent bounded CI packaging corrections are tracked in the B06 release log, not redesign work.
|
||||
|
||||
## Test layers
|
||||
|
||||
| Layer | Setup and demonstrated scope | Limit |
|
||||
|---|---|---|
|
||||
| Frontend unit/component | Jest, jsdom, Testing Library; [config](../../../job-tracker-ui/jest.config.cjs). Account switching, routes, workspace/drafts, CV, mail, admin, theme, translations, dialogs and imports/exports | Babel strips TypeScript; mocks do not prove server ownership or real provider behavior |
|
||||
| General browser | [Playwright config](../../../job-tracker-ui/playwright.config.ts): one Chromium project, isolated .NET API/SQLite data and local frontend; production static build supported | Chromium only; no actual Traefik/nginx; no cross-browser or screen-reader certification |
|
||||
| Browser smoke | Nine cases in `e2e/smoke.spec.ts`: health/readiness, public plans, login, Free restrictions, reviewed job create, deep-linked job workspace/dirty guard, career, public CV/PDF, long searchable Code PDF | Selected journeys, not exhaustive editor states or all providers |
|
||||
| Account isolation | Four `e2e/account-isolation.spec.ts` cases: original A→B replay, missing/forged context, crafted CV ownership/association, two-tab private-state disposal/Back | Retain API and database assertions when UI changes |
|
||||
| Accessibility | Two axe cases over eight sampled routes | See missing state matrix below |
|
||||
| Other general browser | One each discovery responsive review, dark Kanban, CSV security/UTF-8 byte preservation | Does not establish whole-app mobile/theme parity |
|
||||
| PDF HTTP probe | `pdf-tests/admission.spec.ts` and dedicated config | Synthetic bounded concurrent requests; admission differs from time-window limiting |
|
||||
| Rate-limit HTTP probe | `rate-limit-tests/isolation.spec.ts` and dedicated config | Nine account/session/IP/auth/forwarding scenarios; native API topology |
|
||||
| Production ingress HTTP | `ingress-tests/production.spec.ts` and dedicated config | Six native production-mode origin/proxy checks; not running nginx or Traefik |
|
||||
| Backend | xUnit/Moq, SQLite/InMemory and HTTP test seams; API/service ownership, auth, parser, CV/history/PDF, queue, billing, export, migration and rate/proxy tests | Provider-host tests and fault/probe tests have separate runtime requirements; SQLite is not full MariaDB proof |
|
||||
| Repository/dependencies | Compose rendering + 17 hostile mutations, secret scan/SBOM, evaluation and supply-chain scripts | Config validation cannot prove host firewall or actual socket peers |
|
||||
| Adjacent clients/services | Browser-extension node tests and Python parser/service tests | Preserve capture/document boundary; avoid pretending these are covered by React Jest |
|
||||
|
||||
The default browser suite currently contains **18 tests**. The nine special browser/HTTP files count includes six general e2e files and three separately configured suites. Special configurations must be invoked explicitly; a plain general Playwright run does not run all of them.
|
||||
|
||||
## Existing evidence versus fresh execution
|
||||
|
||||
| Evidence | Result and classification |
|
||||
|---|---|
|
||||
| Previous B06 unchanged application regression | 166 focused backend, 3 Compose, 6 production HTTP, 9 rate-limit HTTP passed; [exact prior commands/results](../../audits/2026-09-07/validation/b06-completion.md) |
|
||||
| Previous B06 broader baseline | 915 selected backend tests, 298 frontend tests/67 suites, 18 browser tests, Release builds and targeted lint passed; external-DNS-dependent IMAP test excluded locally and explicitly documented |
|
||||
| Fresh Phase 1 type reproduction | From `job-tracker-ui`: `node node_modules/typescript/bin/tsc --noEmit --incremental false` → exit 1, `src/interview-prep.test.tsx(120,10): error TS2571: Object is of type 'unknown'.` |
|
||||
| Fresh release-prerequisite checks | `python scripts/test-ingress.py` → 3/3 pass; real standalone Compose path also tested; official downloaded Linux binary digest verified; tracked-secret scan and diff check pass |
|
||||
| Fresh packaging regression at `23cc250` | Explicit installed .NET 9.0.317 SDK: Release build + **22/22 PDF admission tests** pass, then **915/915 selected backend tests** pass (same documented external-DNS IMAP exclusion). Results: `.artifacts/redesign-audit/backend.trx` |
|
||||
| Actual CI push verification | Runs 736/737 exposed missing Compose/token prerequisites; corrected. Run 738 passed Compose/safety/extension/parser/API build, then exposed Linux PDF test-fixture packaging collision. Follow-up result belongs in [release log](../../audits/2026-09-07/validation/b06-completion.md#authorized-release-attempt-and-ci-prerequisite-correction) |
|
||||
| Live/container boundary | Local Docker engine unavailable; F04 production evidence remains incomplete. No audit claim of real proxy-chain success |
|
||||
|
||||
The selected broader backend suite was repeated for the PDF fixture packaging change; the frontend suite was not repeated merely for documentation edits. Preserve the distinction between prior unchanged-source evidence, newly executed checks and actual CI failures. Run 739 subsequently failed earlier in the unchanged API compiler with `csc.dll` exit 139 on both existing attempts; it did not reach the corrected test-project build. No test gate was bypassed.
|
||||
|
||||
## Exact TypeScript root cause
|
||||
|
||||
[Interview test:120](../../../job-tracker-ui/src/interview-prep.test.tsx#L120) reads `.content` from `mockedApi.post.mock.calls[0][1]`. Axios's mocked generic request-data argument is typed `unknown`; the test dereferences it without narrowing. The runtime assertion can pass because Babel removes types. The production component's emitted behavior is not shown broken by this test diagnostic.
|
||||
|
||||
[tsconfig](../../../job-tracker-ui/tsconfig.json) includes `src`, including tests. CI runs Jest/lint/Next build but has no explicit full standalone `tsc --noEmit` gate. Next's successful build is not evidence that this exact standalone test-inclusive program passed. Phase 2 should narrow the test payload appropriately and introduce a deliberate full type gate. Do not weaken strictness, blanket-exclude tests or call this a P1 production outage. No type fix was made in Phase 1.
|
||||
|
||||
## Missing regression proof before redesign
|
||||
|
||||
| Priority | Add or preserve evidence |
|
||||
|---|---|
|
||||
| First | Stable type-check gate; B02 stale/queued mutation + cross-tab unmount as shared-client acceptance; legacy URL/overlay/full-page parity |
|
||||
| First | Populated CV editor/profile/job detail plus open menus/dialogs/error/conflict states in EN/NB, light/dark, mobile/desktop; preserve underlying draft/history assertions |
|
||||
| First | AI suggestions rejected/accepted distinctly; actual profile values unchanged when editing a CV/cover letter; unsupported/locked capabilities behave honestly |
|
||||
| First | Typed date values, JSON import/export and B05 CSV bytes; attachments/private/public download distinctions; package history remains frozen |
|
||||
| Before mail migration | Draft revisions, uncertain send/new attempt, provider reconnect/read failure, ownership and explicit send confirmation; use synthetic/sandbox providers |
|
||||
| Before admin migration | Non-admin denied APIs, role revocation and last-admin guards, sensitive diagnostics excluded from personal pages |
|
||||
| Before public release | Keyboard + NVDA/Narrator, preview scroll/focus, zoom/reflow, forced colors, real mobile keyboard and touch; provider/production gates separately |
|
||||
|
||||
Axe currently scans `/`, `/login`, `/dashboard`, `/jobs`, `/kanban`, `/career`, `/settings`, `/admin/system`, mostly after `body`/`main` appears, in English. Missing builder library/editor, job detail, discovery, offers, mail/review, public CV, account security, registration/reset/verification, operations, admin users/audit and interactive loaded states must be selected intentionally. Do not convert a green shell sample into a WCAG compliance claim.
|
||||
|
||||
Recommended later commands: locked dependency restore; Release backend build/test; full Jest; standalone tsc; lint; production frontend build; general Playwright static-export suite; explicit PDF/rate/ingress configurations; Compose validator and `git diff --check`. Use the environment/setup commands from the completion reports rather than guessing SDK paths or running probes against production.
|
||||
@@ -0,0 +1,76 @@
|
||||
// Read-only source census for the Phase 1 audit. Uses the repository's installed TypeScript parser.
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const cp = require('child_process');
|
||||
const root = process.cwd();
|
||||
const ts = require(path.join(root, 'job-tracker-ui/node_modules/typescript'));
|
||||
const out = path.join(root, 'docs/redesign/audit');
|
||||
fs.mkdirSync(out, {recursive:true});
|
||||
const paths = cp.execFileSync('git', ['ls-files'], {encoding:'utf8'}).trim().split('\n');
|
||||
const files = paths.filter(p => /^job-tracker-ui\/(src|app)\/.+\.[jt]sx?$/.test(p) && !/\.test\./.test(p) && !p.endsWith('setupTests.ts'));
|
||||
const tests = paths.filter(p => /(?:\.test\.[jt]sx?$|\.spec\.tsx?$)/.test(p) && p.startsWith('job-tracker-ui/'));
|
||||
const sources = {};
|
||||
const routes = [];
|
||||
function loc(sf,n) { return sf.getLineAndCharacterOfPosition(n.getStart(sf)).line + 1; }
|
||||
function resolve(from, dep) {
|
||||
if (!dep.startsWith('.')) return null;
|
||||
const base = path.posix.normalize(path.posix.join(path.posix.dirname(from),dep));
|
||||
return [base, ...['.ts','.tsx','.js','.jsx','/index.ts','/index.tsx'].map(s=>base+s)].find(p=>files.includes(p)) || null;
|
||||
}
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(path.join(root,file),'utf8');
|
||||
const sf = ts.createSourceFile(file,content,ts.ScriptTarget.Latest,true,file.endsWith('tsx')?ts.ScriptKind.TSX:ts.ScriptKind.TS);
|
||||
const info = {lines:content.split(/\r?\n/).length, imports:[], api:[], labels:[], components:[], storage:[], functions:[]};
|
||||
function visit(n) {
|
||||
if(ts.isImportDeclaration(n) && ts.isStringLiteral(n.moduleSpecifier)) info.imports.push(n.moduleSpecifier.text);
|
||||
if(ts.isCallExpression(n)) {
|
||||
if(n.expression.kind===ts.SyntaxKind.ImportKeyword && n.arguments[0] && ts.isStringLiteral(n.arguments[0])) info.imports.push(n.arguments[0].text);
|
||||
if(ts.isPropertyAccessExpression(n.expression) && /^(api|axios)$/.test(n.expression.expression.getText(sf)) && /^(get|post|put|patch|delete|request)$/.test(n.expression.name.text)) info.api.push({line:loc(sf,n),method:n.expression.name.text.toUpperCase(),url:n.arguments[0]?.getText(sf)||''});
|
||||
if(n.expression.getText(sf)==='t' && n.arguments[0] && ts.isStringLiteral(n.arguments[0])) info.labels.push(n.arguments[0].text);
|
||||
if(/(?:localStorage|sessionStorage)\.(?:getItem|setItem|removeItem)$/.test(n.expression.getText(sf))) info.storage.push({line:loc(sf,n),call:n.getText(sf).replace(/\s+/g,' ').slice(0,220)});
|
||||
}
|
||||
if((ts.isFunctionDeclaration(n)||ts.isVariableDeclaration(n)) && n.name && /^[A-Z]/.test(n.name.getText(sf))) info.functions.push({name:n.name.getText(sf),line:loc(sf,n)});
|
||||
if(ts.isJsxOpeningElement(n)||ts.isJsxSelfClosingElement(n)) {
|
||||
const tag=n.tagName.getText(sf);
|
||||
if(/^[A-Z]/.test(tag)) info.components.push(tag);
|
||||
if(tag==='Route') {
|
||||
const attrs=Object.fromEntries(n.attributes.properties.filter(ts.isJsxAttribute).map(a=>[a.name.getText(sf),a.initializer?.getText(sf)||'']));
|
||||
routes.push({file,line:loc(sf,n),...attrs});
|
||||
}
|
||||
}
|
||||
if(file.endsWith('/App.tsx') && ts.isPropertyAssignment(n) && n.name.getText(sf)==='path' && ts.isStringLiteral(n.initializer)) routes.push({file,line:loc(sf,n),path:n.initializer.text,element:n.parent.getText(sf).replace(/\s+/g,' ')});
|
||||
ts.forEachChild(n,visit);
|
||||
}
|
||||
visit(sf);
|
||||
for(const key of ['imports','labels','components']) info[key]=[...new Set(info[key])].sort();
|
||||
info.dependencies=info.imports.map(i=>resolve(file,i)).filter(Boolean);
|
||||
sources[file]=info;
|
||||
}
|
||||
const reachable = new Set();
|
||||
function walk(file) { if(reachable.has(file)||!sources[file])return; reachable.add(file); sources[file].dependencies.forEach(walk); }
|
||||
walk('job-tracker-ui/src/ClientApp.tsx');
|
||||
for (const [file,info] of Object.entries(sources)) {
|
||||
info.reachableFromClientApp=reachable.has(file);
|
||||
info.importedBy=Object.keys(sources).filter(f=>sources[f].dependencies.includes(file));
|
||||
}
|
||||
const summary = {baseline:cp.execFileSync('git',['rev-parse','HEAD'],{encoding:'utf8'}).trim(),sourceFiles:files.length,frontendTestFiles:tests.length,apiCallSites:Object.values(sources).reduce((n,s)=>n+s.api.length,0),routeDeclarations:routes.length};
|
||||
fs.writeFileSync(path.join(out,'source-inventory.json'),JSON.stringify({summary,routes,tests,sources},null,2)+'\n');
|
||||
const cell=s=>String(s).replaceAll('|','\\|').replaceAll('\n',' ');
|
||||
const link=(file,line)=>`[${file.replace('job-tracker-ui/','')}:${line}](../../../${file}#L${line})`;
|
||||
// docs/redesign/audit is three directories below the repository root.
|
||||
const sourceLink=link;
|
||||
let api='# API call-site inventory\n\nGenerated with the installed TypeScript AST from the committed baseline. Each row is an actual `api`/`axios` call expression, not a claim of runtime test coverage. Paths are relative to the shared `/api` base; interpolations are preserved. Domain wrappers are included. Companion technical audit maps contracts and authorization.\n\n| Source | Method | URL expression |\n|---|---|---|\n';
|
||||
for(const [file,info] of Object.entries(sources)) for(const call of info.api) api+=`| ${sourceLink(file,call.line)} | ${call.method} | ${cell(call.url)} |\n`;
|
||||
fs.writeFileSync(path.join(out,'API_CALL_SITES.md'),api);
|
||||
let components='# Component and source inventory\n\nEvery production TSX module under `src` and `app` is listed. Lines are size indicators, not complexity scores. Reachability is relative-import reachability from ClientApp; app entry files are expected to be outside that graph. MUI primitives are dependencies, not missing local components. No unreachable file is approved for deletion.\n\n| Module | Lines | Client graph | Local direct consumers | Rendered component names |\n|---|---|---|---|---|\n';
|
||||
for(const [file,info] of Object.entries(sources)) if(file.endsWith('.tsx')) components+=`| ${sourceLink(file,1)} | ${info.lines} | ${info.reachableFromClientApp?'reachable':'outside graph'} | ${cell(info.importedBy.map(f=>path.basename(f)).join(', ')||'—')} | ${cell(info.components.join(', '))} |\n`;
|
||||
fs.writeFileSync(path.join(out,'COMPONENT_INVENTORY.md'),components);
|
||||
let testList='# Test file inventory\n\nTracked test files at the audit baseline. Presence is not proof that a feature or every interaction is covered. See TEST_INVENTORY.md for scope and execution evidence.\n\n| Layer | File |\n|---|---|\n';
|
||||
for(const file of paths.filter(p => tests.includes(p) || /^JobTrackerApi.Tests\/.+\.cs$/.test(p) && /Tests?\.cs$/.test(p) || /^browser-extension\/tests\/.+\.test\.mjs$/.test(p) || /^tools\/summarizer\/tests\/.+\.py$/.test(p) || /^scripts\/test-.+\.py$/.test(p))) {
|
||||
const layer=file.startsWith('job-tracker-ui/src/')?'Frontend unit/component':file.startsWith('job-tracker-ui/')?'Browser / HTTP':file.startsWith('JobTrackerApi.Tests/')?'Backend':file.startsWith('tools/')?'Parser / AI service':file.startsWith('browser-extension/')?'Browser extension':'Repository safety';
|
||||
testList+=`| ${layer} | ${sourceLink(file,1)} |\n`;
|
||||
}
|
||||
fs.writeFileSync(path.join(out,'TEST_FILES.md'),testList);
|
||||
console.log(JSON.stringify(summary));
|
||||
console.log('Largest:',Object.entries(sources).sort((a,b)=>b[1].lines-a[1].lines).slice(0,12).map(([f,s])=>[f,s.lines]));
|
||||
console.log('Outside graph:',Object.entries(sources).filter(([f,s])=>f.endsWith('.tsx')&&!s.reachableFromClientApp).map(([f])=>f));
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user